ROSE  0.9.11.56
SqlDatabase.h
1 #ifndef ROSE_SqlDatabase_H
2 #define ROSE_SqlDatabase_H
3 
4 #include "FormatRestorer.h"
5 #include "RoseException.h"
6 #include "StringUtility.h"
7 #include "rose_override.h"
8 
9 #include <boost/enable_shared_from_this.hpp>
10 #include <boost/shared_ptr.hpp>
11 
12 #include <cassert>
13 #include <iomanip>
14 #include <stdexcept>
15 #include <stdint.h>
16 #include <string>
17 #include <sstream>
18 #include <vector>
19 
118 namespace SqlDatabase {
119 
121 enum Driver {
125 };
126 
127 
128 /*******************************************************************************************************************************
129  * Forwards and types
130  *******************************************************************************************************************************/
131 
132 class Connection;
133 class ConnectionImpl;
134 class Transaction;
135 class TransactionImpl;
136 class Statement;
137 class StatementImpl;
138 
142 typedef boost::shared_ptr<Connection> ConnectionPtr;
143 
147 typedef boost::shared_ptr<Transaction> TransactionPtr;
148 
152 typedef boost::shared_ptr<Statement> StatementPtr;
153 
154 // Data type used in templates to indicate lack of a column
155 class NoColumn {};
156 
157 /*******************************************************************************************************************************
158  * Exceptions
159  *******************************************************************************************************************************/
160 
162 class Exception: public Rose::Exception {
163 public:
164  explicit Exception(const char *mesg): Rose::Exception(mesg) {}
165  explicit Exception(const std::string &mesg): Rose::Exception(mesg) {}
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) {}
169 
170  virtual ~Exception() throw() {}
171  virtual const char *what() const throw() ROSE_OVERRIDE;
172  void print(std::ostream&) const;
173  ConnectionPtr connection;
174  TransactionPtr transaction;
175  StatementPtr statement;
176 private:
177  mutable std::string what_str; // backing store for what()
178 };
179 
180 
181 /*******************************************************************************************************************************
182  * Connections
183  *******************************************************************************************************************************/
184 
191 class Connection: public boost::enable_shared_from_this<Connection> {
192  friend class TransactionImpl;
193  friend class Transaction;
194  friend class StatementImpl;
195 public:
201  static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER) {
202  if (NO_DRIVER==driver) {
203  if (NO_DRIVER==(driver = guess_driver(open_spec)))
204  throw Exception("no suitable driver for \""+open_spec+"\"");
205  }
206  return ConnectionPtr(new Connection(open_spec, driver));
207  }
208 
212  TransactionPtr transaction();
213 
216  static Driver guess_driver(const std::string &open_spec);
217 
219  Driver driver() const;
220 
222  std::string openspec() const;
223 
227  void set_debug(FILE *f);
228  FILE *get_debug() const;
232  void print(std::ostream&) const;
233 
234  // Only called by boost::shared_ptr
235  ~Connection() { finish(); }
236 
238  static std::string connectionSpecification(const std::string &uri, Driver driver = NO_DRIVER);
239 
240 protected:
241  // Protected because you should be using create() to get a smart pointer. Database driver-level connections are typically
242  // not copyable object anyway.
243  Connection(const std::string &open_spec, Driver driver): impl(NULL) { init(open_spec, driver); }
244 
245 private:
246  void init(const std::string &open_spec, Driver driver);
247  void finish();
248 
249 private:
250  ConnectionImpl *impl;
251 };
252 
253 /*******************************************************************************************************************************
254  * Transactions
255  *******************************************************************************************************************************/
256 
262 class Transaction: public boost::enable_shared_from_this<Transaction> {
263  friend class ConnectionImpl;
264  friend class Statement;
265  friend class StatementImpl;
266 public:
270  static TransactionPtr create(const ConnectionPtr &conn);
271 
275  void rollback();
276 
280  void commit();
281 
284  bool is_terminated() const;
285 
287  StatementPtr statement(const std::string &sql);
288 
292  void execute(const std::string &sql);
293 
297  void bulk_load(const std::string &tablename, std::istream&);
298 
300  Driver driver() const;
301 
303  ConnectionPtr connection() const;
304 
309  void set_debug(FILE *f);
310  FILE *get_debug() const;
314  void print(std::ostream&) const;
315 
316  // Only called by boost::shared_ptr
317  ~Transaction() { finish(); }
318 
319 protected:
320  explicit Transaction(const ConnectionPtr &conn, size_t drv_conn): impl(NULL) { init(conn, drv_conn); }
321 
322 private:
323  void init(const ConnectionPtr &conn, size_t drv_conn);
324  void finish();
325 
326 private:
327  TransactionImpl *impl;
328 };
329 
330 
331 /*******************************************************************************************************************************
332  * Statements
333  *******************************************************************************************************************************/
334 
343 class Statement: public boost::enable_shared_from_this<Statement> {
344 public:
345 
348  static StatementPtr create(const TransactionPtr &tranx, const std::string &sql) {
349  return StatementPtr(new Statement(tranx, sql));
350  }
351 
355  class iterator {
356  public:
357  iterator(): execution_seq(0), row_num(0) { init(); } // an end iterator
358  iterator(const StatementPtr &stmt, size_t execution_seq)
359  : stmt(stmt), execution_seq(execution_seq), row_num(0) { init(); }
360  template<typename T> T get(size_t idx);
361  int32_t get_i32(size_t idx);
362  int64_t get_i64(size_t idx);
363  uint32_t get_u32(size_t idx);
364  uint64_t get_u64(size_t idx);
365  double get_dbl(size_t idx);
366  std::string get_str(size_t idx);
367  std::vector<uint8_t> get_blob(size_t idx);
368  iterator& operator++();
369  bool at_eof() const;
370  bool operator==(const iterator &other) const;
371  bool operator!=(const iterator &other) const { return !(*this==other); }
372  private:
373  void init();
374  void check() const; // check that this iterator is not stale
375  private:
376  StatementPtr stmt; // statement whose results we are iterating over
377  size_t execution_seq; // statement execution counter
378  size_t row_num; // row number
379  };
380 
385  StatementPtr bind(size_t idx, int32_t val);
386  StatementPtr bind(size_t idx, int64_t val);
387  StatementPtr bind(size_t idx, uint32_t val);
388  StatementPtr bind(size_t idx, uint64_t val);
389  StatementPtr bind(size_t idx, double val);
390  StatementPtr bind(size_t idx, const std::string &val);
391  StatementPtr bind(size_t idx, const std::vector<uint8_t> &val);
392  StatementPtr bind_null(size_t idx);
396  iterator begin();
397 
400  iterator end() { return iterator(); }
401 
403  void execute();
404 
406  int execute_int();
407 
409  double execute_double();
410 
412  std::string execute_string();
413 
415  std::vector<uint8_t> execute_blob();
416 
418  Driver driver() const;
419 
421  TransactionPtr transaction() const;
422 
427  void set_debug(FILE *f);
428  FILE *get_debug() const;
432  void print(std::ostream&) const;
433 
434 public:
435  // Called only by boost::shared_ptr
436  ~Statement() { finish(); }
437 
438 protected:
439  Statement(const TransactionPtr &tranx, const std::string &sql): impl(NULL) { init(tranx, sql); }
440 
441 private:
442  void init(const TransactionPtr &tranx, const std::string &sql);
443  void finish();
444 
445 private:
446  StatementImpl *impl;
447 };
448 
449 template<> NoColumn Statement::iterator::get<NoColumn>(size_t idx);
450 template<> int64_t Statement::iterator::get<int64_t>(size_t idx);
451 template<> uint64_t Statement::iterator::get<uint64_t>(size_t idx);
452 template<> int32_t Statement::iterator::get<int32_t>(size_t idx);
453 template<> uint32_t Statement::iterator::get<uint32_t>(size_t idx);
454 template<> float Statement::iterator::get<float>(size_t idx);
455 template<> double Statement::iterator::get<double>(size_t idx);
456 template<> std::string Statement::iterator::get<std::string>(size_t idx);
457 
458 /*******************************************************************************************************************************
459  * Miscellaneous functions
460  *******************************************************************************************************************************/
461 
463 std::string uriDocumentation();
464 
466 std::vector<std::string> split_sql(const std::string &sql);
467 
469 std::string escape(const std::string&, Driver, bool do_quote=true);
470 
472 std::string hexSequence(const std::vector<uint8_t> &v, Driver driver);
473 
475 bool is_valid_table_name(const std::string &name);
476 
478 template<class Container>
479 std::string in(const Container &values)
480 {
481  std::ostringstream retval;
482  retval <<"in (";
483  unsigned nvals = 0;
484  for (typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi, ++nvals)
485  retval <<(nvals?", ":"") <<*vi;
486  retval <<")";
487  return retval.str();
488 }
489 
491 template<class Container, class Stringifier>
492 std::string in_numbers(const Container &values, Stringifier &stringifier)
493 {
494  return "in (" + Rose::StringUtility::join(", ", Rose::StringUtility::toStrings(values, stringifier)) + ")";
495 }
496 
499 template<class Container>
500 std::string in_strings(const Container &values, Driver driver)
501 {
502  std::vector<std::string> strings;
503  for (typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi)
504  strings.push_back(escape(*vi, driver));
505  return in(strings);
506 }
507 
508 std::ostream& operator<<(std::ostream&, const NoColumn&);
509 std::ostream& operator<<(std::ostream&, const Exception&);
510 std::ostream& operator<<(std::ostream&, const Connection&);
511 std::ostream& operator<<(std::ostream&, const Transaction&);
512 std::ostream& operator<<(std::ostream&, const Statement&);
513 
514 /*******************************************************************************************************************************
515  * Tables
516  *******************************************************************************************************************************/
517 
518 // The things here that don't have doxygen comments are not intended to be used directly by users.
519 
520 template<typename> struct ColumnTraits {
521  enum { valid_column = 1 };
522 };
523 template<> struct ColumnTraits<NoColumn> {
524  enum { valid_column = 0 };
525 };
526 
528 template<typename T>
529 class Renderer {
530 public:
531  virtual ~Renderer() {}
532 
535  virtual std::string operator()(const T &value, size_t width) const {
536  std::ostringstream ss;
537  ss <<value;
538  return ss.str();
539  }
540 };
541 
542 // Specialized for string-valued columns in order to left-justify the string by padding it on the right with an
543 // appropriate number of SPC characters.
544 template<>
545 class Renderer<std::string> {
546 public:
547  virtual ~Renderer() {}
548  virtual std::string operator()(const std::string &value, size_t width) const {
549  return value + std::string(width, ' ');
550  }
551 };
552 
554 struct AddrRenderer: Renderer<uint64_t> {
555  size_t nbits; // number of bits in addresses; higher addresses will result in more digits
556  explicit AddrRenderer(size_t nbits=32): nbits(nbits) {}
557  virtual std::string operator()(const uint64_t &value, size_t width) const ROSE_OVERRIDE {
558  return Rose::StringUtility::addrToString(value, nbits);
559  }
560 };
561 extern AddrRenderer addr8Renderer;
562 extern AddrRenderer addr16Renderer;
563 extern AddrRenderer addr32Renderer;
564 extern AddrRenderer addr64Renderer;
567 struct TimeRenderer: Renderer<time_t> {
568  bool local_tz;
569  std::string format;
570  TimeRenderer(): local_tz(true), format("%F %T %z") {}
571  explicit TimeRenderer(const std::string &format, bool local_tz=true): local_tz(local_tz), format(format) {}
572  virtual std::string operator()(const time_t &value, size_t width) const ROSE_OVERRIDE;
573 };
574 extern TimeRenderer timeRenderer;
575 extern TimeRenderer dateRenderer;
576 extern TimeRenderer humanTimeRenderer;
579 template<typename Table>
580 class PrePostRow {
581 public:
582  virtual ~PrePostRow() {}
583  virtual void operator()(std::ostream &out, const Table *table, size_t rownum, const std::vector<size_t> &widths) {}
584 };
585 
586 // Prints a header
587 template<typename T>
588 class Header {
589 public:
590  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {
591  FormatRestorer fr(out);
592  out <<prefix <<std::setw(width) <<hdr;
593  }
594 };
595 template<>
596 class Header<std::string> {
597 public:
598  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {
599  FormatRestorer fr(out);
600  out <<prefix <<std::setw(width) <<std::left <<hdr;
601  }
602 };
603 template<>
604 class Header<NoColumn> {
605 public:
606  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {}
607 };
608 
609 // Prints a row separator for a single column
610 template<typename T>
612 public:
613  void operator()(std::ostream &out, const std::string &prefix, size_t width) {
614  out <<prefix <<std::string(width, '-');
615  }
616 };
617 template<>
619 public:
620  void operator()(std::ostream &out, const std::string &prefix, size_t width) {}
621 };
622 
696 template<typename T00, typename T01=NoColumn, typename T02=NoColumn, typename T03=NoColumn,
697  typename T04=NoColumn, typename T05=NoColumn, typename T06=NoColumn, typename T07=NoColumn,
698  typename T08=NoColumn, typename T09=NoColumn, typename T10=NoColumn, typename T11=NoColumn,
699  typename T12=NoColumn, typename T13=NoColumn, typename T14=NoColumn, typename T15=NoColumn>
700 class Table {
701 public:
702  enum {
703  MAXCOLS=16,
704  };
705 
707  struct Tuple { // We could use boost::tuple, but it has a 10-member limit.
708  explicit Tuple(const T00 &v0, const T01 &v1 =T01(), const T02 &v2 =T02(), const T03 &v3 =T03(),
709  const T04 &v4 =T04(), const T05 &v5 =T05(), const T06 &v6 =T06(), const T07 &v7 =T07(),
710  const T08 &v8 =T08(), const T09 &v9 =T09(), const T10 &v10=T10(), const T11 &v11=T11(),
711  const T12 &v12=T12(), const T13 &v13=T13(), const T14 &v14=T14(), const T15 &v15=T15())
712  : v0(v0), v1(v1), v2(v2), v3(v3), v4(v4), v5(v5), v6(v6), v7(v7),
713  v8(v8), v9(v9), v10(v10), v11(v11), v12(v12), v13(v13), v14(v14), v15(v15) {}
714  T00 v0; T01 v1; T02 v2; T03 v3; T04 v4; T05 v5; T06 v6; T07 v7;
715  T08 v8; T09 v9; T10 v10; T11 v11; T12 v12; T13 v13; T14 v14; T15 v15;
716  };
717 
719  struct Renderers { // We could use boost::tuple, but it has a 10-member limit.
720  explicit Renderers(const Renderer<T00> *r0 =NULL, const Renderer<T01> *r1 =NULL,
721  const Renderer<T02> *r2 =NULL, const Renderer<T03> *r3 =NULL,
722  const Renderer<T04> *r4 =NULL, const Renderer<T05> *r5 =NULL,
723  const Renderer<T06> *r6 =NULL, const Renderer<T07> *r7 =NULL,
724  const Renderer<T08> *r8 =NULL, const Renderer<T09> *r9 =NULL,
725  const Renderer<T10> *r10=NULL, const Renderer<T11> *r11=NULL,
726  const Renderer<T12> *r12=NULL, const Renderer<T13> *r13=NULL,
727  const Renderer<T14> *r14=NULL, const Renderer<T15> *r15=NULL)
728  : r0(r0), r1(r1), r2(r2), r3(r3), r4(r4), r5(r5), r6(r6), r7(r7),
729  r8(r8), r9(r9), r10(r10), r11(r11), r12(r12), r13(r13), r14(r14), r15(r15) {}
730  const Renderer<T00> *r0; const Renderer<T01> *r1; const Renderer<T02> *r2; const Renderer<T03> *r3;
731  const Renderer<T04> *r4; const Renderer<T05> *r5; const Renderer<T06> *r6; const Renderer<T07> *r7;
732  const Renderer<T08> *r8; const Renderer<T09> *r9; const Renderer<T10> *r10; const Renderer<T11> *r11;
733  const Renderer<T12> *r12; const Renderer<T13> *r13; const Renderer<T14> *r14; const Renderer<T15> *r15;
734  };
735 
737  typedef std::vector<Tuple> Rows;
738 
740  Table(): headers_(MAXCOLS), colsep_(" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {}
741 
743  explicit Table(const StatementPtr &stmt)
744  : headers_(MAXCOLS), colsep_(" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {
745  insert(stmt);
746  }
747 
750  void header(int colnum, const std::string &hdr) {
751  assert(colnum<headers_.size());
752  headers_[colnum] = hdr;
753  }
754  const std::string& header(int colnum) const {
755  assert(colnum<headers_.size());
756  return headers_[colnum];
757  }
758  void headers(const std::string &h0, const std::string &h1="", const std::string &h2="", const std::string &h3="",
759  const std::string &h4="", const std::string &h5="", const std::string &h6="", const std::string &h7="",
760  const std::string &h8="", const std::string &h9="", const std::string &h10="", const std::string &h11="",
761  const std::string &h12="", const std::string &h13="", const std::string &h14="", const std::string &h15="") {
762  headers_[ 0] = h0; headers_[ 1] = h1; headers_[ 2] = h2; headers_[ 3] = h3;
763  headers_[ 4] = h4; headers_[ 5] = h5; headers_[ 6] = h6; headers_[ 7] = h7;
764  headers_[ 8] = h8; headers_[ 9] = h9; headers_[10] = h10; headers_[11] = h11;
765  headers_[12] = h12; headers_[13] = h13; headers_[14] = h14; headers_[15] = h15;
766  }
771  void reprint_headers(size_t nrows) { reprint_headers_ = nrows; }
772  size_t reprint_headers() const { return reprint_headers_; }
791  Renderers& renderers() { return render_; }
792  const Renderers& renderers() const { return render_; }
798  pre_row_ = pre;
799  post_row_ = post;
800  }
801  std::pair<PrePostRow<Table>*, PrePostRow<Table>*> prepost() const {
802  return std::make_pair(pre_row_, post_row_);
803  }
807  size_t size() const { return rows_.size(); }
808 
810  bool empty() const { return rows_.empty(); }
811 
813  void clear() { rows_.clear(); }
814 
817  Tuple& operator[](size_t i) { assert(i<rows_.size()); return rows_[i]; }
818  const Tuple& operator[](size_t i) const { assert(i<rows_.size()); return rows_[i]; }
824  void insert(const Tuple &tuple) { rows_.push_back(tuple); }
825  void insert(const T00 &v00, const T01 &v01=T01(), const T02 &v02=T02(), const T03 &v03=T03(),
826  const T04 &v04=T04(), const T05 &v05=T05(), const T06 &v06=T06(), const T07 &v07=T07(),
827  const T08 &v08=T08(), const T09 &v09=T09(), const T10 &v10=T10(), const T11 &v11=T11(),
828  const T12 &v12=T12(), const T13 &v13=T13(), const T14 &v14=T14(), const T15 &v15=T15()) {
829  rows_.push_back(Tuple(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14, v15));
830  }
834  void insert(const StatementPtr &stmt) {
835  for (Statement::iterator row=stmt->begin(); row!=stmt->end(); ++row) {
836  rows_.push_back(Tuple(row.get<T00>( 0), row.get<T01>( 1), row.get<T02>( 2), row.get<T03>( 3),
837  row.get<T04>( 4), row.get<T05>( 5), row.get<T06>( 6), row.get<T07>( 7),
838  row.get<T08>( 8), row.get<T09>( 9), row.get<T10>(10), row.get<T11>(11),
839  row.get<T12>(12), row.get<T13>(13), row.get<T14>(14), row.get<T15>(15)));
840  }
841  }
842 
845  void line_prefix(const std::string &s) { prefix_ = s; }
846  const std::string& line_prefix() const { return prefix_; }
850  template<typename T>
851  std::string render(const Renderer<T> *r, const T &value, size_t width=0) const {
852  Renderer<T> r_;
853  if (NULL==r)
854  r = &r_;
855  std::string s = (*r)(value, width);
856  if (width!=0)
857  s = s.substr(0, width);
858  return s;
859  }
860 
863  std::vector<size_t> colsizes() const {
864  std::vector<size_t> widths(MAXCOLS, 0);
865  for (typename Rows::const_iterator ri=rows_.begin(); ri!=rows_.end(); ++ri) {
866  widths[ 0] = std::max(widths[ 0], render(render_.r0, ri->v0 ).size());
867  widths[ 1] = std::max(widths[ 1], render(render_.r1, ri->v1 ).size());
868  widths[ 2] = std::max(widths[ 2], render(render_.r2, ri->v2 ).size());
869  widths[ 3] = std::max(widths[ 3], render(render_.r3, ri->v3 ).size());
870  widths[ 4] = std::max(widths[ 4], render(render_.r4, ri->v4 ).size());
871  widths[ 5] = std::max(widths[ 5], render(render_.r5, ri->v5 ).size());
872  widths[ 6] = std::max(widths[ 6], render(render_.r6, ri->v6 ).size());
873  widths[ 7] = std::max(widths[ 7], render(render_.r7, ri->v7 ).size());
874  widths[ 8] = std::max(widths[ 8], render(render_.r8, ri->v8 ).size());
875  widths[ 9] = std::max(widths[ 9], render(render_.r9, ri->v9 ).size());
876  widths[10] = std::max(widths[10], render(render_.r10, ri->v10).size());
877  widths[11] = std::max(widths[11], render(render_.r11, ri->v11).size());
878  widths[12] = std::max(widths[12], render(render_.r12, ri->v12).size());
879  widths[13] = std::max(widths[13], render(render_.r13, ri->v13).size());
880  widths[14] = std::max(widths[14], render(render_.r14, ri->v14).size());
881  widths[15] = std::max(widths[15], render(render_.r15, ri->v15).size());
882  }
883  return widths;
884  }
885 
887  void print_headers(std::ostream &out, const std::vector<size_t> &widths) const {
888  Header<T00>()(out, prefix_, headers_[ 0], widths[ 0]);
889  Header<T01>()(out, colsep_, headers_[ 1], widths[ 1]);
890  Header<T02>()(out, colsep_, headers_[ 2], widths[ 2]);
891  Header<T03>()(out, colsep_, headers_[ 3], widths[ 3]);
892  Header<T04>()(out, colsep_, headers_[ 4], widths[ 4]);
893  Header<T05>()(out, colsep_, headers_[ 5], widths[ 5]);
894  Header<T06>()(out, colsep_, headers_[ 6], widths[ 6]);
895  Header<T07>()(out, colsep_, headers_[ 7], widths[ 7]);
896  Header<T08>()(out, colsep_, headers_[ 8], widths[ 8]);
897  Header<T09>()(out, colsep_, headers_[ 9], widths[ 9]);
898  Header<T10>()(out, colsep_, headers_[10], widths[10]);
899  Header<T11>()(out, colsep_, headers_[11], widths[11]);
900  Header<T12>()(out, colsep_, headers_[12], widths[12]);
901  Header<T13>()(out, colsep_, headers_[13], widths[13]);
902  Header<T14>()(out, colsep_, headers_[14], widths[14]);
903  Header<T15>()(out, colsep_, headers_[15], widths[15]);
904  out <<"\n";
905  }
906 
908  void print_rowsep(std::ostream &out, const std::vector<size_t> &widths) const {
909  std::string colsep = colsep_;
910  for (size_t i=0; i<colsep.size(); ++i) {
911  if (isspace(colsep[i])) {
912  colsep[i] = '-';
913  } else if ('|'==colsep[i]) {
914  colsep[i] = '+';
915  }
916  }
917  RowSeparator<T00>()(out, prefix_, widths[ 0]);
918  RowSeparator<T01>()(out, colsep, widths[ 1]);
919  RowSeparator<T02>()(out, colsep, widths[ 2]);
920  RowSeparator<T03>()(out, colsep, widths[ 3]);
921  RowSeparator<T04>()(out, colsep, widths[ 4]);
922  RowSeparator<T05>()(out, colsep, widths[ 5]);
923  RowSeparator<T06>()(out, colsep, widths[ 6]);
924  RowSeparator<T07>()(out, colsep, widths[ 7]);
925  RowSeparator<T08>()(out, colsep, widths[ 8]);
926  RowSeparator<T09>()(out, colsep, widths[ 9]);
927  RowSeparator<T10>()(out, colsep, widths[10]);
928  RowSeparator<T11>()(out, colsep, widths[11]);
929  RowSeparator<T12>()(out, colsep, widths[12]);
930  RowSeparator<T13>()(out, colsep, widths[13]);
931  RowSeparator<T14>()(out, colsep, widths[14]);
932  RowSeparator<T15>()(out, colsep, widths[15]);
933  out <<"\n";
934  }
935 
937  void
938  print_row(std::ostream &out, const Tuple &t, const std::vector<size_t> &widths) const {
939  FormatRestorer fr(out);
940  out << prefix_ <<std::setw(widths[ 0]) <<render(render_.r0, t.v0, widths[ 0])
941  <<(ColumnTraits<T01>::valid_column ? colsep_ : "") <<std::setw(widths[ 1]) <<render(render_.r1, t.v1, widths[ 1])
942  <<(ColumnTraits<T02>::valid_column ? colsep_ : "") <<std::setw(widths[ 2]) <<render(render_.r2, t.v2, widths[ 2])
943  <<(ColumnTraits<T03>::valid_column ? colsep_ : "") <<std::setw(widths[ 3]) <<render(render_.r3, t.v3, widths[ 3])
944  <<(ColumnTraits<T04>::valid_column ? colsep_ : "") <<std::setw(widths[ 4]) <<render(render_.r4, t.v4, widths[ 4])
945  <<(ColumnTraits<T05>::valid_column ? colsep_ : "") <<std::setw(widths[ 5]) <<render(render_.r5, t.v5, widths[ 5])
946  <<(ColumnTraits<T06>::valid_column ? colsep_ : "") <<std::setw(widths[ 6]) <<render(render_.r6, t.v6, widths[ 6])
947  <<(ColumnTraits<T07>::valid_column ? colsep_ : "") <<std::setw(widths[ 7]) <<render(render_.r7, t.v7, widths[ 7])
948  <<(ColumnTraits<T08>::valid_column ? colsep_ : "") <<std::setw(widths[ 8]) <<render(render_.r8, t.v8, widths[ 8])
949  <<(ColumnTraits<T09>::valid_column ? colsep_ : "") <<std::setw(widths[ 9]) <<render(render_.r9, t.v9, widths[ 9])
950  <<(ColumnTraits<T10>::valid_column ? colsep_ : "") <<std::setw(widths[10]) <<render(render_.r10, t.v10, widths[10])
951  <<(ColumnTraits<T11>::valid_column ? colsep_ : "") <<std::setw(widths[11]) <<render(render_.r11, t.v11, widths[11])
952  <<(ColumnTraits<T12>::valid_column ? colsep_ : "") <<std::setw(widths[12]) <<render(render_.r12, t.v12, widths[12])
953  <<(ColumnTraits<T13>::valid_column ? colsep_ : "") <<std::setw(widths[13]) <<render(render_.r13, t.v13, widths[13])
954  <<(ColumnTraits<T14>::valid_column ? colsep_ : "") <<std::setw(widths[14]) <<render(render_.r14, t.v14, widths[14])
955  <<(ColumnTraits<T15>::valid_column ? colsep_ : "") <<std::setw(widths[15]) <<render(render_.r15, t.v15, widths[15])
956  <<"\n";
957  }
958 
960  void print(std::ostream &out) const {
961  std::vector<size_t> widths = colsizes();
962 
963  // Headers
964  bool has_headers = false;
965  for (size_t i=0; i<MAXCOLS; ++i) {
966  widths[i] = std::max(widths[i], headers_[i].size());
967  if (!headers_[i].empty())
968  has_headers = true;
969  }
970  if (has_headers) {
971  print_headers(out, widths);
972  print_rowsep(out, widths);
973  }
974 
975  // Body
976  if (rows_.empty()) {
977  out <<prefix_ <<"(0 rows)\n\n";
978  } else {
979  for (size_t i=0; i<rows_.size(); ++i) {
980  if (i>0 && has_headers && reprint_headers_>0 && 0==i%reprint_headers_) {
981  print_rowsep(out, widths);
982  print_headers(out, widths);
983  print_rowsep(out, widths);
984  }
985  if (pre_row_)
986  (*pre_row_)(out, this, i, widths);
987  print_row(out, rows_[i], widths);
988  if (post_row_)
989  (*post_row_)(out, this, i, widths);
990  }
991  }
992 
993  // Epilogue
994  if (has_headers && !rows_.empty())
995  print_rowsep(out, widths);
996  }
997 
998 private:
999  std::vector<std::string> headers_;
1000  Renderers render_;
1001  Rows rows_;
1002  std::string colsep_;
1003  PrePostRow<Table> *pre_row_, *post_row_;
1004  size_t reprint_headers_;
1005  std::string prefix_; // string printed before every line of output
1006 };
1007 
1008 } // namespace
1009 #endif
std::string in(const Container &values)
Converts a container of values to an SQL "in" clause.
Definition: SqlDatabase.h:479
std::vector< Tuple > Rows
All rows of a table.
Definition: SqlDatabase.h:737
Functors for rendering column values.
Definition: SqlDatabase.h:719
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.
Definition: SqlDatabase.h:754
void set_debug(FILE *f)
Debugging property.
size_t size() const
Return the number of rows in the table.
Definition: SqlDatabase.h:807
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.
Definition: SqlDatabase.h:801
Tuple & operator[](size_t i)
Return a reference to a particular row.
Definition: SqlDatabase.h:817
Connection to a database.
Definition: SqlDatabase.h:191
static TransactionPtr create(const ConnectionPtr &conn)
Create a new transaction.
bool empty() const
Returns true if table has no rows.
Definition: SqlDatabase.h:810
std::vector< size_t > colsizes() const
Compute column widths.
Definition: SqlDatabase.h:863
void reprint_headers(size_t nrows)
How often should headers be reprinted?
Definition: SqlDatabase.h:771
AddrRenderer addr8Renderer
Renders 8-bit addresses in hexadecimal.
static StatementPtr create(const TransactionPtr &tranx, const std::string &sql)
Create a new statement.
Definition: SqlDatabase.h:348
void print(std::ostream &) const
Print some basic info about this transaction.
In-memory representation of a database table.
Definition: SqlDatabase.h:700
A database operation.
Definition: SqlDatabase.h:343
std::string escape(const std::string &, Driver, bool do_quote=true)
Produce an SQL string literal from a C++ string.
Maximum number of columns allowed in a table.
Definition: SqlDatabase.h:703
boost::shared_ptr< Transaction > TransactionPtr
Shared-ownership pointer to a transaction.
Definition: SqlDatabase.h:147
int execute_int()
Execute a statement that returns a single integer.
std::string format
Format, as for strftime().
Definition: SqlDatabase.h:569
std::string in_strings(const Container &values, Driver driver)
Converts a container of strings to an SQL "in" clause of strings.
Definition: SqlDatabase.h:500
Called before and after printing each row of a table.
Definition: SqlDatabase.h:580
STL namespace.
void clear()
Clear the table by removing all rows.
Definition: SqlDatabase.h:813
TransactionPtr transaction() const
Returns the transaction for this statement.
Renders a column value as a string.
Definition: SqlDatabase.h:529
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.
Definition: SqlDatabase.h:554
void print(std::ostream &) const
Print some basic info about this connection.
void print_row(std::ostream &out, const Tuple &t, const std::vector< size_t > &widths) const
Print one row of a table.
Definition: SqlDatabase.h:938
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.
Definition: SqlDatabase.h:123
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.
Definition: SqlDatabase.h:825
void header(int colnum, const std::string &hdr)
Headers to use when printing the table.
Definition: SqlDatabase.h:750
iterator end()
Returns an end iterator.
Definition: SqlDatabase.h:400
Restores output stream flags to original values.
Table(const StatementPtr &stmt)
Creates a new table and initializes it by running the specified database query.
Definition: SqlDatabase.h:743
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.
Definition: SqlDatabase.h:851
bool local_tz
Use local time zone rather than GMT.
Definition: SqlDatabase.h:568
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.
Definition: SqlDatabase.h:162
void prepost(PrePostRow< Table > *pre, PrePostRow< Table > *post)
Accessor for functors called before and after each row is printed.
Definition: SqlDatabase.h:797
virtual std::string operator()(const T &value, size_t width) const
Renders a column value as a string.
Definition: SqlDatabase.h:535
void execute()
Execute a statement and ignore its result rows if it has any.
Support for a variety of relational database drivers.
Definition: SqlDatabase.h:118
void line_prefix(const std::string &s)
String to print at the beginning of every line of output.
Definition: SqlDatabase.h:845
FILE * get_debug() const
Debugging property.
Renderers & renderers()
Accessor for value renderers.
Definition: SqlDatabase.h:791
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.
Definition: SqlDatabase.h:908
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.
Definition: SqlDatabase.h:557
static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER)
Create a new database connection.
Definition: SqlDatabase.h:201
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.
Definition: SqlDatabase.h:887
Iterates over the result rows.
Definition: SqlDatabase.h:355
const Renderers & renderers() const
Accessor for value renderers.
Definition: SqlDatabase.h:792
void insert(const Tuple &tuple)
Add a new row to the end of the table.
Definition: SqlDatabase.h:824
Used only by the default Connection constructor.
Definition: SqlDatabase.h:122
const Tuple & operator[](size_t i) const
Return a reference to a particular row.
Definition: SqlDatabase.h:818
boost::shared_ptr< Connection > ConnectionPtr
Shared-ownership pointer to a database connection.
Definition: SqlDatabase.h:137
std::string in_numbers(const Container &values, Stringifier &stringifier)
Converts a container of numbers to an SQL "in" clause using StringUtility to format them...
Definition: SqlDatabase.h:492
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?
Definition: SqlDatabase.h:772
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.
Definition: SqlDatabase.h:262
void execute(const std::string &sql)
Execute one or more statements.
One row of a table.
Definition: SqlDatabase.h:707
iterator begin()
Execute this statement.
boost::shared_ptr< Statement > StatementPtr
Shared-ownership pointer to a statement.
Definition: SqlDatabase.h:152
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.
Definition: SqlDatabase.h:846
Renders a time_t as a string.
Definition: SqlDatabase.h:567
Table()
Creates a new, empty table.
Definition: SqlDatabase.h:740
void print(std::ostream &out) const
Print all rows of the table to the specified stream.
Definition: SqlDatabase.h:960
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.
FILE * get_debug() const
Debugging property.
Base class for all ROSE exceptions.
Definition: RoseException.h:9
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.
Definition: SqlDatabase.h:758
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.
Definition: SqlDatabase.h:121
void insert(const StatementPtr &stmt)
Insert more rows into a table by running the specified query.
Definition: SqlDatabase.h:834