1 #ifndef ROSE_SqlDatabase_H
2 #define ROSE_SqlDatabase_H
4 #include <Rose/FormatRestorer.h>
5 #include "Rose/Exception.h"
6 #include <Rose/StringUtility.h>
7 #include "rose_override.h"
9 #include <boost/enable_shared_from_this.hpp>
10 #include <boost/shared_ptr.hpp>
133 class ConnectionImpl;
135 class TransactionImpl;
166 explicit Exception(
const std::string &mesg,
const ConnectionPtr &conn,
const TransactionPtr &tx,
167 const StatementPtr &stmt)
168 :
Rose::Exception(mesg), connection(conn), transaction(tx), statement(stmt) {}
171 virtual const char *what()
const throw() ROSE_OVERRIDE;
172 void print(std::ostream&)
const;
173 ConnectionPtr connection;
174 TransactionPtr transaction;
175 StatementPtr statement;
177 mutable std::string what_str;
191 class Connection:
public boost::enable_shared_from_this<Connection> {
192 friend class TransactionImpl;
194 friend class StatementImpl;
196 typedef std::pair<std::string , std::string > Parameter;
202 std::vector<Parameter> params;
217 throw Exception(
"no suitable driver for \""+open_spec+
"\"");
245 void print(std::ostream&)
const;
254 static ParsedUrl
parseUrl(std::string url);
259 Connection(
const std::string &open_spec,
Driver driver): impl(NULL) { init(open_spec, driver); }
266 ConnectionImpl *impl;
278 class Transaction:
public boost::enable_shared_from_this<Transaction> {
279 friend class ConnectionImpl;
281 friend class StatementImpl;
286 static TransactionPtr
create(
const ConnectionPtr &conn);
303 StatementPtr
statement(
const std::string &sql);
308 void execute(
const std::string &sql);
313 void bulk_load(
const std::string &tablename, std::istream&);
330 void print(std::ostream&)
const;
336 explicit Transaction(
const ConnectionPtr &conn,
size_t drv_conn): impl(NULL) { init(conn, drv_conn); }
339 void init(
const ConnectionPtr &conn,
size_t drv_conn);
343 TransactionImpl *impl;
359 class Statement:
public boost::enable_shared_from_this<Statement> {
364 static StatementPtr
create(
const TransactionPtr &tranx,
const std::string &sql) {
373 iterator(): execution_seq(0), row_num(0) { init(); }
374 iterator(
const StatementPtr &stmt,
size_t execution_seq)
375 : stmt(stmt), execution_seq(execution_seq), row_num(0) { init(); }
376 template<
typename T> T
get(
size_t idx);
377 int32_t get_i32(
size_t idx);
378 int64_t get_i64(
size_t idx);
379 uint32_t get_u32(
size_t idx);
380 uint64_t get_u64(
size_t idx);
381 double get_dbl(
size_t idx);
382 std::string get_str(
size_t idx);
383 std::vector<uint8_t> get_blob(
size_t idx);
386 bool operator==(
const iterator &other)
const;
387 bool operator!=(
const iterator &other)
const {
return !(*
this==other); }
393 size_t execution_seq;
401 StatementPtr
bind(
size_t idx, int32_t val);
402 StatementPtr
bind(
size_t idx, int64_t val);
403 StatementPtr
bind(
size_t idx, uint32_t val);
404 StatementPtr
bind(
size_t idx, uint64_t val);
405 StatementPtr
bind(
size_t idx,
double val);
406 StatementPtr
bind(
size_t idx,
const std::string &val);
407 StatementPtr
bind(
size_t idx,
const std::vector<uint8_t> &val);
448 void print(std::ostream&)
const;
455 Statement(
const TransactionPtr &tranx,
const std::string &sql): impl(NULL) { init(tranx, sql); }
458 void init(
const TransactionPtr &tranx,
const std::string &sql);
465 template<> NoColumn Statement::iterator::get<NoColumn>(
size_t idx);
466 template<> int64_t Statement::iterator::get<int64_t>(
size_t idx);
467 template<> uint64_t Statement::iterator::get<uint64_t>(
size_t idx);
468 template<> int32_t Statement::iterator::get<int32_t>(
size_t idx);
469 template<> uint32_t Statement::iterator::get<uint32_t>(
size_t idx);
470 template<>
float Statement::iterator::get<float>(
size_t idx);
471 template<>
double Statement::iterator::get<double>(
size_t idx);
472 template<> std::string Statement::iterator::get<std::string>(
size_t idx);
482 std::vector<std::string>
split_sql(
const std::string &sql);
485 std::string
escape(
const std::string&,
Driver,
bool do_quote=
true);
494 template<
class Container>
495 std::string
in(
const Container &values)
497 std::ostringstream retval;
500 for (
typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi, ++nvals)
501 retval <<(nvals?
", ":
"") <<*vi;
507 template<
class Container,
class Stringifier>
508 std::string
in_numbers(
const Container &values, Stringifier &stringifier)
515 template<
class Container>
518 std::vector<std::string> strings;
519 for (
typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi)
520 strings.push_back(
escape(*vi, driver));
524 std::ostream& operator<<(std::ostream&,
const NoColumn&);
525 std::ostream& operator<<(std::ostream&,
const Exception&);
526 std::ostream& operator<<(std::ostream&,
const Connection&);
527 std::ostream& operator<<(std::ostream&,
const Transaction&);
528 std::ostream& operator<<(std::ostream&,
const Statement&);
537 enum { valid_column = 1 };
540 enum { valid_column = 0 };
551 virtual std::string
operator()(
const T &value,
size_t width)
const {
552 std::ostringstream ss;
564 virtual std::string
operator()(
const std::string &value,
size_t width)
const {
565 return value + std::string(width,
' ');
573 virtual std::string
operator()(
const uint64_t &value,
size_t width)
const ROSE_OVERRIDE {
587 explicit TimeRenderer(
const std::string &format,
bool local_tz=
true): local_tz(local_tz), format(format) {}
588 virtual std::string
operator()(
const time_t &value,
size_t width)
const ROSE_OVERRIDE;
595 template<
typename Table>
599 virtual void operator()(std::ostream &out,
const Table *table,
size_t rownum,
const std::vector<size_t> &widths) {}
606 void operator()(std::ostream &out,
const std::string &prefix,
const std::string &hdr,
size_t width) {
608 out <<prefix <<std::setw(width) <<hdr;
614 void operator()(std::ostream &out,
const std::string &prefix,
const std::string &hdr,
size_t width) {
616 out <<prefix <<std::setw(width) <<std::left <<hdr;
622 void operator()(std::ostream &out,
const std::string &prefix,
const std::string &hdr,
size_t width) {}
629 void operator()(std::ostream &out,
const std::string &prefix,
size_t width) {
630 out <<prefix <<std::string(width,
'-');
636 void operator()(std::ostream &out,
const std::string &prefix,
size_t width) {}
724 explicit Tuple(
const T00 &v0,
const T01 &v1 =T01(),
const T02 &v2 =T02(),
const T03 &v3 =T03(),
725 const T04 &v4 =T04(),
const T05 &v5 =T05(),
const T06 &v6 =T06(),
const T07 &v7 =T07(),
726 const T08 &v8 =T08(),
const T09 &v9 =T09(),
const T10 &v10=T10(),
const T11 &v11=T11(),
727 const T12 &v12=T12(),
const T13 &v13=T13(),
const T14 &v14=T14(),
const T15 &v15=T15())
728 : v0(v0), v1(v1), v2(v2), v3(v3), v4(v4), v5(v5), v6(v6), v7(v7),
729 v8(v8), v9(v9), v10(v10), v11(v11), v12(v12), v13(v13), v14(v14), v15(v15) {}
730 T00 v0; T01 v1; T02 v2; T03 v3; T04 v4; T05 v5; T06 v6; T07 v7;
731 T08 v8; T09 v9; T10 v10; T11 v11; T12 v12; T13 v13; T14 v14; T15 v15;
744 : r0(r0), r1(r1), r2(r2), r3(r3), r4(r4), r5(r5), r6(r6), r7(r7),
745 r8(r8), r9(r9), r10(r10), r11(r11), r12(r12), r13(r13), r14(r14), r15(r15) {}
753 typedef std::vector<Tuple>
Rows;
756 Table(): headers_(
MAXCOLS), colsep_(
" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {}
759 explicit Table(
const StatementPtr &stmt)
760 : headers_(
MAXCOLS), colsep_(
" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {
766 void header(
int colnum,
const std::string &hdr) {
767 assert(colnum<headers_.size());
768 headers_[colnum] = hdr;
770 const std::string&
header(
int colnum)
const {
771 assert(colnum<headers_.size());
772 return headers_[colnum];
774 void headers(
const std::string &h0,
const std::string &h1=
"",
const std::string &h2=
"",
const std::string &h3=
"",
775 const std::string &h4=
"",
const std::string &h5=
"",
const std::string &h6=
"",
const std::string &h7=
"",
776 const std::string &h8=
"",
const std::string &h9=
"",
const std::string &h10=
"",
const std::string &h11=
"",
777 const std::string &h12=
"",
const std::string &h13=
"",
const std::string &h14=
"",
const std::string &h15=
"") {
778 headers_[ 0] = h0; headers_[ 1] = h1; headers_[ 2] = h2; headers_[ 3] = h3;
779 headers_[ 4] = h4; headers_[ 5] = h5; headers_[ 6] = h6; headers_[ 7] = h7;
780 headers_[ 8] = h8; headers_[ 9] = h9; headers_[10] = h10; headers_[11] = h11;
781 headers_[12] = h12; headers_[13] = h13; headers_[14] = h14; headers_[15] = h15;
818 return std::make_pair(pre_row_, post_row_);
823 size_t size()
const {
return rows_.size(); }
826 bool empty()
const {
return rows_.empty(); }
841 void insert(
const T00 &v00,
const T01 &v01=T01(),
const T02 &v02=T02(),
const T03 &v03=T03(),
842 const T04 &v04=T04(),
const T05 &v05=T05(),
const T06 &v06=T06(),
const T07 &v07=T07(),
843 const T08 &v08=T08(),
const T09 &v09=T09(),
const T10 &v10=T10(),
const T11 &v11=T11(),
844 const T12 &v12=T12(),
const T13 &v13=T13(),
const T14 &v14=T14(),
const T15 &v15=T15()) {
845 rows_.push_back(
Tuple(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14, v15));
852 rows_.push_back(
Tuple(row.get<T00>( 0), row.get<T01>( 1), row.get<T02>( 2), row.get<T03>( 3),
853 row.get<T04>( 4), row.get<T05>( 5), row.get<T06>( 6), row.get<T07>( 7),
854 row.get<T08>( 8), row.get<T09>( 9), row.get<T10>(10), row.get<T11>(11),
855 row.get<T12>(12), row.get<T13>(13), row.get<T14>(14), row.get<T15>(15)));
871 std::string s = (*r)(value, width);
873 s = s.substr(0, width);
880 std::vector<size_t> widths(
MAXCOLS, 0);
881 for (
typename Rows::const_iterator ri=rows_.begin(); ri!=rows_.end(); ++ri) {
882 widths[ 0] = std::max(widths[ 0],
render(render_.r0, ri->v0 ).size());
883 widths[ 1] = std::max(widths[ 1],
render(render_.r1, ri->v1 ).size());
884 widths[ 2] = std::max(widths[ 2],
render(render_.r2, ri->v2 ).size());
885 widths[ 3] = std::max(widths[ 3],
render(render_.r3, ri->v3 ).size());
886 widths[ 4] = std::max(widths[ 4],
render(render_.r4, ri->v4 ).size());
887 widths[ 5] = std::max(widths[ 5],
render(render_.r5, ri->v5 ).size());
888 widths[ 6] = std::max(widths[ 6],
render(render_.r6, ri->v6 ).size());
889 widths[ 7] = std::max(widths[ 7],
render(render_.r7, ri->v7 ).size());
890 widths[ 8] = std::max(widths[ 8],
render(render_.r8, ri->v8 ).size());
891 widths[ 9] = std::max(widths[ 9],
render(render_.r9, ri->v9 ).size());
892 widths[10] = std::max(widths[10],
render(render_.r10, ri->v10).size());
893 widths[11] = std::max(widths[11],
render(render_.r11, ri->v11).size());
894 widths[12] = std::max(widths[12],
render(render_.r12, ri->v12).size());
895 widths[13] = std::max(widths[13],
render(render_.r13, ri->v13).size());
896 widths[14] = std::max(widths[14],
render(render_.r14, ri->v14).size());
897 widths[15] = std::max(widths[15],
render(render_.r15, ri->v15).size());
903 void print_headers(std::ostream &out,
const std::vector<size_t> &widths)
const {
904 Header<T00>()(out, prefix_, headers_[ 0], widths[ 0]);
905 Header<T01>()(out, colsep_, headers_[ 1], widths[ 1]);
906 Header<T02>()(out, colsep_, headers_[ 2], widths[ 2]);
907 Header<T03>()(out, colsep_, headers_[ 3], widths[ 3]);
908 Header<T04>()(out, colsep_, headers_[ 4], widths[ 4]);
909 Header<T05>()(out, colsep_, headers_[ 5], widths[ 5]);
910 Header<T06>()(out, colsep_, headers_[ 6], widths[ 6]);
911 Header<T07>()(out, colsep_, headers_[ 7], widths[ 7]);
912 Header<T08>()(out, colsep_, headers_[ 8], widths[ 8]);
913 Header<T09>()(out, colsep_, headers_[ 9], widths[ 9]);
914 Header<T10>()(out, colsep_, headers_[10], widths[10]);
915 Header<T11>()(out, colsep_, headers_[11], widths[11]);
916 Header<T12>()(out, colsep_, headers_[12], widths[12]);
917 Header<T13>()(out, colsep_, headers_[13], widths[13]);
918 Header<T14>()(out, colsep_, headers_[14], widths[14]);
919 Header<T15>()(out, colsep_, headers_[15], widths[15]);
924 void print_rowsep(std::ostream &out,
const std::vector<size_t> &widths)
const {
925 std::string colsep = colsep_;
926 for (
size_t i=0; i<colsep.size(); ++i) {
927 if (isspace(colsep[i])) {
929 }
else if (
'|'==colsep[i]) {
954 print_row(std::ostream &out,
const Tuple &t,
const std::vector<size_t> &widths)
const {
956 out << prefix_ <<std::setw(widths[ 0]) <<
render(render_.r0, t.v0, widths[ 0])
976 void print(std::ostream &out)
const {
977 std::vector<size_t> widths =
colsizes();
980 bool has_headers =
false;
981 for (
size_t i=0; i<
MAXCOLS; ++i) {
982 widths[i] = std::max(widths[i], headers_[i].
size());
983 if (!headers_[i].
empty())
993 out <<prefix_ <<
"(0 rows)\n\n";
995 for (
size_t i=0; i<rows_.size(); ++i) {
996 if (i>0 && has_headers && reprint_headers_>0 && 0==i%reprint_headers_) {
1002 (*pre_row_)(out,
this, i, widths);
1005 (*post_row_)(out,
this, i, widths);
1010 if (has_headers && !rows_.empty())
1015 std::vector<std::string> headers_;
1018 std::string colsep_;
1020 size_t reprint_headers_;
1021 std::string prefix_;
Broken-out info about a URL.
std::string in(const Container &values)
Converts a container of values to an SQL "in" clause.
std::vector< Tuple > Rows
All rows of a table.
Functors for rendering column values.
static Driver guess_driver(const std::string &open_spec)
Guess a driver based on a connection specification.
const std::string & header(int colnum) const
Headers to use when printing the table.
void set_debug(FILE *f)
Debugging property.
size_t size() const
Return the number of rows in the table.
void commit()
Complete a transaction.
TimeRenderer humanTimeRenderer
Renders a time using the current locale, which is more human-friendly.
std::pair< PrePostRow< Table > *, PrePostRow< Table > * > prepost() const
Accessor for functors called before and after each row is printed.
Tuple & operator[](size_t i)
Return a reference to a particular row.
Connection to a database.
static TransactionPtr create(const ConnectionPtr &conn)
Create a new transaction.
bool empty() const
Returns true if table has no rows.
std::vector< size_t > colsizes() const
Compute column widths.
void reprint_headers(size_t nrows)
How often should headers be reprinted?
AddrRenderer addr8Renderer
Renders 8-bit addresses in hexadecimal.
static StatementPtr create(const TransactionPtr &tranx, const std::string &sql)
Create a new statement.
void print(std::ostream &) const
Print some basic info about this transaction.
In-memory representation of a database table.
std::string escape(const std::string &, Driver, bool do_quote=true)
Produce an SQL string literal from a C++ string.
boost::shared_ptr< Transaction > TransactionPtr
Shared-ownership pointer to a transaction.
int execute_int()
Execute a statement that returns a single integer.
std::string format
Format, as for strftime().
std::string in_strings(const Container &values, Driver driver)
Converts a container of strings to an SQL "in" clause of strings.
Called before and after printing each row of a table.
void clear()
Clear the table by removing all rows.
TransactionPtr transaction() const
Returns the transaction for this statement.
Renders a column value as a string.
std::vector< std::string > split_sql(const std::string &sql)
Split SQL source code into individual statements.
void bulk_load(const std::string &tablename, std::istream &)
Bulk load data into table.
Renders a rose_addr_t as a hexadecimal string.
void print(std::ostream &) const
Print some basic info about this connection.
static ParsedUrl parseUrl(std::string url)
Parse a URL to return its parts.
void print_row(std::ostream &out, const Tuple &t, const std::vector< size_t > &widths) const
Print one row of a table.
void print(std::ostream &) const
Print some basic info about this statement.
bool is_valid_table_name(const std::string &name)
Returns true if name is a valid table name.
static std::string connectionSpecification(const std::string &uri, Driver driver=NO_DRIVER)
Converts a uniform resource locator to a driver specific string.
SQLite3 using the C++ sqlite3x API.
bool is_terminated() const
Returns termination status.
void insert(const T00 &v00, const T01 &v01=T01(), const T02 &v02=T02(), const T03 &v03=T03(), const T04 &v04=T04(), const T05 &v05=T05(), const T06 &v06=T06(), const T07 &v07=T07(), const T08 &v08=T08(), const T09 &v09=T09(), const T10 &v10=T10(), const T11 &v11=T11(), const T12 &v12=T12(), const T13 &v13=T13(), const T14 &v14=T14(), const T15 &v15=T15())
Add a new row to the end of the table.
void header(int colnum, const std::string &hdr)
Headers to use when printing the table.
iterator end()
Returns an end iterator.
Table(const StatementPtr &stmt)
Creates a new table and initializes it by running the specified database query.
Driver driver() const
Returns the low-level driver name for this statement.
ConnectionPtr connection() const
Returns the connection for this transaction.
std::string render(const Renderer< T > *r, const T &value, size_t width=0) const
Render a single value.
bool local_tz
Use local time zone rather than GMT.
double execute_double()
Execute a statement that returns a single double.
std::string hexSequence(const std::vector< uint8_t > &v, Driver driver)
Produce an SQL hexadecimal sequence from an uint8_t vector.
AddrRenderer addr64Renderer
Renders 64-bit addresses in hexadecimal.
Exceptions thrown by database operations.
void prepost(PrePostRow< Table > *pre, PrePostRow< Table > *post)
Accessor for functors called before and after each row is printed.
virtual std::string operator()(const T &value, size_t width) const
Renders a column value as a string.
void execute()
Execute a statement and ignore its result rows if it has any.
Support for a variety of relational database drivers.
void line_prefix(const std::string &s)
String to print at the beginning of every line of output.
FILE * get_debug() const
Debugging property.
Renderers & renderers()
Accessor for value renderers.
void print_rowsep(std::ostream &out, const std::vector< size_t > &widths) const
Print the row separator that goes between the headers and the data.
std::vector< std::string > toStrings(const Container &numbers, const Stringifier &stringifier=numberToString)
Converts a bunch of numbers to strings.
void set_debug(FILE *f)
Debugging property.
StatementPtr bind_null(size_t idx)
Bind value to a '?' placeholder in the SQL statement.
ROSE_UTIL_API std::string addrToString(uint64_t value, size_t nbits=0)
Convert a virtual address to a string.
std::string uriDocumentation()
Documentation about database connection URIs.
TransactionPtr transaction()
Begins a new transaction for this connection.
virtual std::string operator()(const uint64_t &value, size_t width) const
Renders a column value as a string.
static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER)
Create a new database connection.
AddrRenderer addr16Renderer
Renders 16-bit addresses in hexadecimal.
void print_headers(std::ostream &out, const std::vector< size_t > &widths) const
Print the headers for a table.
Iterates over the result rows.
const Renderers & renderers() const
Accessor for value renderers.
void insert(const Tuple &tuple)
Add a new row to the end of the table.
Used only by the default Connection constructor.
const Tuple & operator[](size_t i) const
Return a reference to a particular row.
boost::shared_ptr< Connection > ConnectionPtr
Shared-ownership pointer to a database connection.
std::string in_numbers(const Container &values, Stringifier &stringifier)
Converts a container of numbers to an SQL "in" clause using StringUtility to format them...
std::string openspec() const
Returns the open specification used when the connection was established.
std::string join(const std::string &separator, const Container &container)
Join individual items to form a single string.
size_t reprint_headers() const
How often should headers be reprinted?
StatementPtr bind(size_t idx, int32_t val)
Bind value to a '?' placeholder in the SQL statement.
void rollback()
Cancel a transaction.
FILE * get_debug() const
Debugging property.
void set_debug(FILE *f)
Debugging property.
Unit of work within a database.
void execute(const std::string &sql)
Execute one or more statements.
iterator begin()
Execute this statement.
boost::shared_ptr< Statement > StatementPtr
Shared-ownership pointer to a statement.
Driver driver() const
Return the low-level driver being used.
TimeRenderer timeRenderer
Renders time_t as YYYY-MM-DD HH:MM:SS in the local timezone.
const std::string & line_prefix() const
String to print at the beginning of every line of output.
Renders a time_t as a string.
Table()
Creates a new, empty table.
void print(std::ostream &out) const
Print all rows of the table to the specified stream.
StatementPtr statement(const std::string &sql)
Create a new statement.
AddrRenderer addr32Renderer
Renders 32-bit addresses in hexadecimal.
TimeRenderer dateRenderer
Renders only the date portion of a time as YYYY-MM-DD in local timezone.
Maximum number of columns allowed in a table.
FILE * get_debug() const
Debugging property.
Base class for all ROSE exceptions.
std::vector< uint8_t > execute_blob()
Execute a statement that returns a single blob.
Driver driver() const
Returns the low-level driver name for this transaction.
void headers(const std::string &h0, const std::string &h1="", const std::string &h2="", const std::string &h3="", const std::string &h4="", const std::string &h5="", const std::string &h6="", const std::string &h7="", const std::string &h8="", const std::string &h9="", const std::string &h10="", const std::string &h11="", const std::string &h12="", const std::string &h13="", const std::string &h14="", const std::string &h15="")
Headers to use when printing the table.
virtual std::string operator()(const time_t &value, size_t width) const
Renders a column value as a string.
std::string execute_string()
Execute a statement that returns a single std::string.
Driver
Low-level driver to use for the database.
void insert(const StatementPtr &stmt)
Insert more rows into a table by running the specified query.