ROSE  0.9.9.109
SqlDatabase.h
1 #ifndef ROSE_SqlDatabase_H
2 #define ROSE_SqlDatabase_H
3 
4 #include "FormatRestorer.h"
5 #include "StringUtility.h"
6 #include "rose_override.h"
7 
8 #include <boost/enable_shared_from_this.hpp>
9 #include <boost/shared_ptr.hpp>
10 
11 #include <cassert>
12 #include <iomanip>
13 #include <stdexcept>
14 #include <stdint.h>
15 #include <string>
16 #include <sstream>
17 #include <vector>
18 
117 namespace SqlDatabase {
118 
120 enum Driver {
124 };
125 
126 
127 /*******************************************************************************************************************************
128  * Forwards and types
129  *******************************************************************************************************************************/
130 
131 class Connection;
132 class ConnectionImpl;
133 class Transaction;
134 class TransactionImpl;
135 class Statement;
136 class StatementImpl;
137 
141 typedef boost::shared_ptr<Connection> ConnectionPtr;
142 
146 typedef boost::shared_ptr<Transaction> TransactionPtr;
147 
151 typedef boost::shared_ptr<Statement> StatementPtr;
152 
153 // Data type used in templates to indicate lack of a column
154 class NoColumn {};
155 
156 /*******************************************************************************************************************************
157  * Exceptions
158  *******************************************************************************************************************************/
159 
161 class Exception: public std::runtime_error {
162 public:
163  explicit Exception(const char *mesg): std::runtime_error(mesg) {}
164  explicit Exception(const std::string &mesg): std::runtime_error(mesg) {}
165  explicit Exception(const std::runtime_error &e, const ConnectionPtr &conn, const TransactionPtr &tx,
166  const StatementPtr &stmt)
167  : std::runtime_error(e), connection(conn), transaction(tx), statement(stmt) {}
168  explicit Exception(const std::string &mesg, const ConnectionPtr &conn, const TransactionPtr &tx,
169  const StatementPtr &stmt)
170  : std::runtime_error(mesg), connection(conn), transaction(tx), statement(stmt) {}
171 
172  virtual ~Exception() throw() {}
173  virtual const char *what() const throw() ROSE_OVERRIDE;
174  void print(std::ostream&) const;
175  ConnectionPtr connection;
176  TransactionPtr transaction;
177  StatementPtr statement;
178 private:
179  mutable std::string what_str; // backing store for what()
180 };
181 
182 
183 /*******************************************************************************************************************************
184  * Connections
185  *******************************************************************************************************************************/
186 
193 class Connection: public boost::enable_shared_from_this<Connection> {
194  friend class TransactionImpl;
195  friend class Transaction;
196  friend class StatementImpl;
197 public:
203  static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER) {
204  if (NO_DRIVER==driver) {
205  if (NO_DRIVER==(driver = guess_driver(open_spec)))
206  throw Exception("no suitable driver for \""+open_spec+"\"");
207  }
208  return ConnectionPtr(new Connection(open_spec, driver));
209  }
210 
214  TransactionPtr transaction();
215 
218  static Driver guess_driver(const std::string &open_spec);
219 
221  Driver driver() const;
222 
224  std::string openspec() const;
225 
229  void set_debug(FILE *f);
230  FILE *get_debug() const;
234  void print(std::ostream&) const;
235 
236  // Only called by boost::shared_ptr
237  ~Connection() { finish(); }
238 
240  static std::string connectionSpecification(const std::string &uri, Driver driver = NO_DRIVER);
241 
242 protected:
243  // Protected because you should be using create() to get a smart pointer. Database driver-level connections are typically
244  // not copyable object anyway.
245  Connection(const std::string &open_spec, Driver driver): impl(NULL) { init(open_spec, driver); }
246 
247 private:
248  void init(const std::string &open_spec, Driver driver);
249  void finish();
250 
251 private:
252  ConnectionImpl *impl;
253 };
254 
255 /*******************************************************************************************************************************
256  * Transactions
257  *******************************************************************************************************************************/
258 
264 class Transaction: public boost::enable_shared_from_this<Transaction> {
265  friend class ConnectionImpl;
266  friend class Statement;
267  friend class StatementImpl;
268 public:
272  static TransactionPtr create(const ConnectionPtr &conn);
273 
277  void rollback();
278 
282  void commit();
283 
286  bool is_terminated() const;
287 
289  StatementPtr statement(const std::string &sql);
290 
294  void execute(const std::string &sql);
295 
299  void bulk_load(const std::string &tablename, std::istream&);
300 
302  Driver driver() const;
303 
305  ConnectionPtr connection() const;
306 
311  void set_debug(FILE *f);
312  FILE *get_debug() const;
316  void print(std::ostream&) const;
317 
318  // Only called by boost::shared_ptr
319  ~Transaction() { finish(); }
320 
321 protected:
322  explicit Transaction(const ConnectionPtr &conn, size_t drv_conn): impl(NULL) { init(conn, drv_conn); }
323 
324 private:
325  void init(const ConnectionPtr &conn, size_t drv_conn);
326  void finish();
327 
328 private:
329  TransactionImpl *impl;
330 };
331 
332 
333 /*******************************************************************************************************************************
334  * Statements
335  *******************************************************************************************************************************/
336 
345 class Statement: public boost::enable_shared_from_this<Statement> {
346 public:
347 
350  static StatementPtr create(const TransactionPtr &tranx, const std::string &sql) {
351  return StatementPtr(new Statement(tranx, sql));
352  }
353 
357  class iterator {
358  public:
359  iterator(): execution_seq(0), row_num(0) { init(); } // an end iterator
360  iterator(const StatementPtr &stmt, size_t execution_seq)
361  : stmt(stmt), execution_seq(execution_seq), row_num(0) { init(); }
362  template<typename T> T get(size_t idx);
363  int32_t get_i32(size_t idx);
364  int64_t get_i64(size_t idx);
365  uint32_t get_u32(size_t idx);
366  uint64_t get_u64(size_t idx);
367  double get_dbl(size_t idx);
368  std::string get_str(size_t idx);
369  iterator& operator++();
370  bool at_eof() const;
371  bool operator==(const iterator &other) const;
372  bool operator!=(const iterator &other) const { return !(*this==other); }
373  private:
374  void init();
375  void check() const; // check that this iterator is not stale
376  private:
377  StatementPtr stmt; // statement whose results we are iterating over
378  size_t execution_seq; // statement execution counter
379  size_t row_num; // row number
380  };
381 
386  StatementPtr bind(size_t idx, int32_t val);
387  StatementPtr bind(size_t idx, int64_t val);
388  StatementPtr bind(size_t idx, uint32_t val);
389  StatementPtr bind(size_t idx, uint64_t val);
390  StatementPtr bind(size_t idx, double val);
391  StatementPtr bind(size_t idx, const std::string &val);
395  iterator begin();
396 
399  iterator end() { return iterator(); }
400 
402  void execute();
403 
405  int execute_int();
406 
408  double execute_double();
409 
411  std::string execute_string();
412 
413 
414 
416  Driver driver() const;
417 
419  TransactionPtr transaction() const;
420 
425  void set_debug(FILE *f);
426  FILE *get_debug() const;
430  void print(std::ostream&) const;
431 
432 public:
433  // Called only by boost::shared_ptr
434  ~Statement() { finish(); }
435 
436 protected:
437  Statement(const TransactionPtr &tranx, const std::string &sql): impl(NULL) { init(tranx, sql); }
438 
439 private:
440  void init(const TransactionPtr &tranx, const std::string &sql);
441  void finish();
442 
443 private:
444  StatementImpl *impl;
445 };
446 
447 template<> NoColumn Statement::iterator::get<NoColumn>(size_t idx);
448 template<> int64_t Statement::iterator::get<int64_t>(size_t idx);
449 template<> uint64_t Statement::iterator::get<uint64_t>(size_t idx);
450 template<> int32_t Statement::iterator::get<int32_t>(size_t idx);
451 template<> uint32_t Statement::iterator::get<uint32_t>(size_t idx);
452 template<> float Statement::iterator::get<float>(size_t idx);
453 template<> double Statement::iterator::get<double>(size_t idx);
454 template<> std::string Statement::iterator::get<std::string>(size_t idx);
455 
456 /*******************************************************************************************************************************
457  * Miscellaneous functions
458  *******************************************************************************************************************************/
459 
461 std::string uriDocumentation();
462 
464 std::vector<std::string> split_sql(const std::string &sql);
465 
467 std::string escape(const std::string&, Driver, bool do_quote=true);
468 
470 bool is_valid_table_name(const std::string &name);
471 
473 template<class Container>
474 std::string in(const Container &values)
475 {
476  std::ostringstream retval;
477  retval <<"in (";
478  unsigned nvals = 0;
479  for (typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi, ++nvals)
480  retval <<(nvals?", ":"") <<*vi;
481  retval <<")";
482  return retval.str();
483 }
484 
486 template<class Container, class Stringifier>
487 std::string in_numbers(const Container &values, Stringifier &stringifier)
488 {
489  return "in (" + Rose::StringUtility::join(", ", Rose::StringUtility::toStrings(values, stringifier)) + ")";
490 }
491 
494 template<class Container>
495 std::string in_strings(const Container &values, Driver driver)
496 {
497  std::vector<std::string> strings;
498  for (typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi)
499  strings.push_back(escape(*vi, driver));
500  return in(strings);
501 }
502 
503 std::ostream& operator<<(std::ostream&, const NoColumn&);
504 std::ostream& operator<<(std::ostream&, const Exception&);
505 std::ostream& operator<<(std::ostream&, const Connection&);
506 std::ostream& operator<<(std::ostream&, const Transaction&);
507 std::ostream& operator<<(std::ostream&, const Statement&);
508 
509 /*******************************************************************************************************************************
510  * Tables
511  *******************************************************************************************************************************/
512 
513 // The things here that don't have doxygen comments are not intended to be used directly by users.
514 
515 template<typename> struct ColumnTraits {
516  enum { valid_column = 1 };
517 };
518 template<> struct ColumnTraits<NoColumn> {
519  enum { valid_column = 0 };
520 };
521 
523 template<typename T>
524 class Renderer {
525 public:
526  virtual ~Renderer() {}
527 
530  virtual std::string operator()(const T &value, size_t width) const {
531  std::ostringstream ss;
532  ss <<value;
533  return ss.str();
534  }
535 };
536 
537 // Specialized for string-valued columns in order to left-justify the string by padding it on the right with an
538 // appropriate number of SPC characters.
539 template<>
540 class Renderer<std::string> {
541 public:
542  virtual ~Renderer() {}
543  virtual std::string operator()(const std::string &value, size_t width) const {
544  return value + std::string(width, ' ');
545  }
546 };
547 
549 struct AddrRenderer: Renderer<uint64_t> {
550  size_t nbits; // number of bits in addresses; higher addresses will result in more digits
551  explicit AddrRenderer(size_t nbits=32): nbits(nbits) {}
552  virtual std::string operator()(const uint64_t &value, size_t width) const ROSE_OVERRIDE {
553  return Rose::StringUtility::addrToString(value, nbits);
554  }
555 };
556 extern AddrRenderer addr8Renderer;
557 extern AddrRenderer addr16Renderer;
558 extern AddrRenderer addr32Renderer;
559 extern AddrRenderer addr64Renderer;
562 struct TimeRenderer: Renderer<time_t> {
563  bool local_tz;
564  std::string format;
565  TimeRenderer(): local_tz(true), format("%F %T %z") {}
566  explicit TimeRenderer(const std::string &format, bool local_tz=true): local_tz(local_tz), format(format) {}
567  virtual std::string operator()(const time_t &value, size_t width) const ROSE_OVERRIDE;
568 };
569 extern TimeRenderer timeRenderer;
570 extern TimeRenderer dateRenderer;
571 extern TimeRenderer humanTimeRenderer;
574 template<typename Table>
575 class PrePostRow {
576 public:
577  virtual ~PrePostRow() {}
578  virtual void operator()(std::ostream &out, const Table *table, size_t rownum, const std::vector<size_t> &widths) {}
579 };
580 
581 // Prints a header
582 template<typename T>
583 class Header {
584 public:
585  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {
586  FormatRestorer fr(out);
587  out <<prefix <<std::setw(width) <<hdr;
588  }
589 };
590 template<>
591 class Header<std::string> {
592 public:
593  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {
594  FormatRestorer fr(out);
595  out <<prefix <<std::setw(width) <<std::left <<hdr;
596  }
597 };
598 template<>
599 class Header<NoColumn> {
600 public:
601  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {}
602 };
603 
604 // Prints a row separator for a single column
605 template<typename T>
607 public:
608  void operator()(std::ostream &out, const std::string &prefix, size_t width) {
609  out <<prefix <<std::string(width, '-');
610  }
611 };
612 template<>
614 public:
615  void operator()(std::ostream &out, const std::string &prefix, size_t width) {}
616 };
617 
691 template<typename T00, typename T01=NoColumn, typename T02=NoColumn, typename T03=NoColumn,
692  typename T04=NoColumn, typename T05=NoColumn, typename T06=NoColumn, typename T07=NoColumn,
693  typename T08=NoColumn, typename T09=NoColumn, typename T10=NoColumn, typename T11=NoColumn,
694  typename T12=NoColumn, typename T13=NoColumn, typename T14=NoColumn, typename T15=NoColumn>
695 class Table {
696 public:
697  enum {
698  MAXCOLS=16,
699  };
700 
702  struct Tuple { // We could use boost::tuple, but it has a 10-member limit.
703  explicit Tuple(const T00 &v0, const T01 &v1 =T01(), const T02 &v2 =T02(), const T03 &v3 =T03(),
704  const T04 &v4 =T04(), const T05 &v5 =T05(), const T06 &v6 =T06(), const T07 &v7 =T07(),
705  const T08 &v8 =T08(), const T09 &v9 =T09(), const T10 &v10=T10(), const T11 &v11=T11(),
706  const T12 &v12=T12(), const T13 &v13=T13(), const T14 &v14=T14(), const T15 &v15=T15())
707  : v0(v0), v1(v1), v2(v2), v3(v3), v4(v4), v5(v5), v6(v6), v7(v7),
708  v8(v8), v9(v9), v10(v10), v11(v11), v12(v12), v13(v13), v14(v14), v15(v15) {}
709  T00 v0; T01 v1; T02 v2; T03 v3; T04 v4; T05 v5; T06 v6; T07 v7;
710  T08 v8; T09 v9; T10 v10; T11 v11; T12 v12; T13 v13; T14 v14; T15 v15;
711  };
712 
714  struct Renderers { // We could use boost::tuple, but it has a 10-member limit.
715  explicit Renderers(const Renderer<T00> *r0 =NULL, const Renderer<T01> *r1 =NULL,
716  const Renderer<T02> *r2 =NULL, const Renderer<T03> *r3 =NULL,
717  const Renderer<T04> *r4 =NULL, const Renderer<T05> *r5 =NULL,
718  const Renderer<T06> *r6 =NULL, const Renderer<T07> *r7 =NULL,
719  const Renderer<T08> *r8 =NULL, const Renderer<T09> *r9 =NULL,
720  const Renderer<T10> *r10=NULL, const Renderer<T11> *r11=NULL,
721  const Renderer<T12> *r12=NULL, const Renderer<T13> *r13=NULL,
722  const Renderer<T14> *r14=NULL, const Renderer<T15> *r15=NULL)
723  : r0(r0), r1(r1), r2(r2), r3(r3), r4(r4), r5(r5), r6(r6), r7(r7),
724  r8(r8), r9(r9), r10(r10), r11(r11), r12(r12), r13(r13), r14(r14), r15(r15) {}
725  const Renderer<T00> *r0; const Renderer<T01> *r1; const Renderer<T02> *r2; const Renderer<T03> *r3;
726  const Renderer<T04> *r4; const Renderer<T05> *r5; const Renderer<T06> *r6; const Renderer<T07> *r7;
727  const Renderer<T08> *r8; const Renderer<T09> *r9; const Renderer<T10> *r10; const Renderer<T11> *r11;
728  const Renderer<T12> *r12; const Renderer<T13> *r13; const Renderer<T14> *r14; const Renderer<T15> *r15;
729  };
730 
732  typedef std::vector<Tuple> Rows;
733 
735  Table(): headers_(MAXCOLS), colsep_(" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {}
736 
738  explicit Table(const StatementPtr &stmt)
739  : headers_(MAXCOLS), colsep_(" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {
740  insert(stmt);
741  }
742 
745  void header(int colnum, const std::string &hdr) {
746  assert(colnum<headers_.size());
747  headers_[colnum] = hdr;
748  }
749  const std::string& header(int colnum) const {
750  assert(colnum<headers_.size());
751  return headers_[colnum];
752  }
753  void headers(const std::string &h0, const std::string &h1="", const std::string &h2="", const std::string &h3="",
754  const std::string &h4="", const std::string &h5="", const std::string &h6="", const std::string &h7="",
755  const std::string &h8="", const std::string &h9="", const std::string &h10="", const std::string &h11="",
756  const std::string &h12="", const std::string &h13="", const std::string &h14="", const std::string &h15="") {
757  headers_[ 0] = h0; headers_[ 1] = h1; headers_[ 2] = h2; headers_[ 3] = h3;
758  headers_[ 4] = h4; headers_[ 5] = h5; headers_[ 6] = h6; headers_[ 7] = h7;
759  headers_[ 8] = h8; headers_[ 9] = h9; headers_[10] = h10; headers_[11] = h11;
760  headers_[12] = h12; headers_[13] = h13; headers_[14] = h14; headers_[15] = h15;
761  }
766  void reprint_headers(size_t nrows) { reprint_headers_ = nrows; }
767  size_t reprint_headers() const { return reprint_headers_; }
786  Renderers& renderers() { return render_; }
787  const Renderers& renderers() const { return render_; }
793  pre_row_ = pre;
794  post_row_ = post;
795  }
796  std::pair<PrePostRow<Table>*, PrePostRow<Table>*> prepost() const {
797  return std::make_pair(pre_row_, post_row_);
798  }
802  size_t size() const { return rows_.size(); }
803 
805  bool empty() const { return rows_.empty(); }
806 
808  void clear() { rows_.clear(); }
809 
812  Tuple& operator[](size_t i) { assert(i<rows_.size()); return rows_[i]; }
813  const Tuple& operator[](size_t i) const { assert(i<rows_.size()); return rows_[i]; }
819  void insert(const Tuple &tuple) { rows_.push_back(tuple); }
820  void insert(const T00 &v00, const T01 &v01=T01(), const T02 &v02=T02(), const T03 &v03=T03(),
821  const T04 &v04=T04(), const T05 &v05=T05(), const T06 &v06=T06(), const T07 &v07=T07(),
822  const T08 &v08=T08(), const T09 &v09=T09(), const T10 &v10=T10(), const T11 &v11=T11(),
823  const T12 &v12=T12(), const T13 &v13=T13(), const T14 &v14=T14(), const T15 &v15=T15()) {
824  rows_.push_back(Tuple(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14, v15));
825  }
829  void insert(const StatementPtr &stmt) {
830  for (Statement::iterator row=stmt->begin(); row!=stmt->end(); ++row) {
831  rows_.push_back(Tuple(row.get<T00>( 0), row.get<T01>( 1), row.get<T02>( 2), row.get<T03>( 3),
832  row.get<T04>( 4), row.get<T05>( 5), row.get<T06>( 6), row.get<T07>( 7),
833  row.get<T08>( 8), row.get<T09>( 9), row.get<T10>(10), row.get<T11>(11),
834  row.get<T12>(12), row.get<T13>(13), row.get<T14>(14), row.get<T15>(15)));
835  }
836  }
837 
840  void line_prefix(const std::string &s) { prefix_ = s; }
841  const std::string& line_prefix() const { return prefix_; }
845  template<typename T>
846  std::string render(const Renderer<T> *r, const T &value, size_t width=0) const {
847  Renderer<T> r_;
848  if (NULL==r)
849  r = &r_;
850  std::string s = (*r)(value, width);
851  if (width!=0)
852  s = s.substr(0, width);
853  return s;
854  }
855 
858  std::vector<size_t> colsizes() const {
859  std::vector<size_t> widths(MAXCOLS, 0);
860  for (typename Rows::const_iterator ri=rows_.begin(); ri!=rows_.end(); ++ri) {
861  widths[ 0] = std::max(widths[ 0], render(render_.r0, ri->v0 ).size());
862  widths[ 1] = std::max(widths[ 1], render(render_.r1, ri->v1 ).size());
863  widths[ 2] = std::max(widths[ 2], render(render_.r2, ri->v2 ).size());
864  widths[ 3] = std::max(widths[ 3], render(render_.r3, ri->v3 ).size());
865  widths[ 4] = std::max(widths[ 4], render(render_.r4, ri->v4 ).size());
866  widths[ 5] = std::max(widths[ 5], render(render_.r5, ri->v5 ).size());
867  widths[ 6] = std::max(widths[ 6], render(render_.r6, ri->v6 ).size());
868  widths[ 7] = std::max(widths[ 7], render(render_.r7, ri->v7 ).size());
869  widths[ 8] = std::max(widths[ 8], render(render_.r8, ri->v8 ).size());
870  widths[ 9] = std::max(widths[ 9], render(render_.r9, ri->v9 ).size());
871  widths[10] = std::max(widths[10], render(render_.r10, ri->v10).size());
872  widths[11] = std::max(widths[11], render(render_.r11, ri->v11).size());
873  widths[12] = std::max(widths[12], render(render_.r12, ri->v12).size());
874  widths[13] = std::max(widths[13], render(render_.r13, ri->v13).size());
875  widths[14] = std::max(widths[14], render(render_.r14, ri->v14).size());
876  widths[15] = std::max(widths[15], render(render_.r15, ri->v15).size());
877  }
878  return widths;
879  }
880 
882  void print_headers(std::ostream &out, const std::vector<size_t> &widths) const {
883  Header<T00>()(out, prefix_, headers_[ 0], widths[ 0]);
884  Header<T01>()(out, colsep_, headers_[ 1], widths[ 1]);
885  Header<T02>()(out, colsep_, headers_[ 2], widths[ 2]);
886  Header<T03>()(out, colsep_, headers_[ 3], widths[ 3]);
887  Header<T04>()(out, colsep_, headers_[ 4], widths[ 4]);
888  Header<T05>()(out, colsep_, headers_[ 5], widths[ 5]);
889  Header<T06>()(out, colsep_, headers_[ 6], widths[ 6]);
890  Header<T07>()(out, colsep_, headers_[ 7], widths[ 7]);
891  Header<T08>()(out, colsep_, headers_[ 8], widths[ 8]);
892  Header<T09>()(out, colsep_, headers_[ 9], widths[ 9]);
893  Header<T10>()(out, colsep_, headers_[10], widths[10]);
894  Header<T11>()(out, colsep_, headers_[11], widths[11]);
895  Header<T12>()(out, colsep_, headers_[12], widths[12]);
896  Header<T13>()(out, colsep_, headers_[13], widths[13]);
897  Header<T14>()(out, colsep_, headers_[14], widths[14]);
898  Header<T15>()(out, colsep_, headers_[15], widths[15]);
899  out <<"\n";
900  }
901 
903  void print_rowsep(std::ostream &out, const std::vector<size_t> &widths) const {
904  std::string colsep = colsep_;
905  for (size_t i=0; i<colsep.size(); ++i) {
906  if (isspace(colsep[i])) {
907  colsep[i] = '-';
908  } else if ('|'==colsep[i]) {
909  colsep[i] = '+';
910  }
911  }
912  RowSeparator<T00>()(out, prefix_, widths[ 0]);
913  RowSeparator<T01>()(out, colsep, widths[ 1]);
914  RowSeparator<T02>()(out, colsep, widths[ 2]);
915  RowSeparator<T03>()(out, colsep, widths[ 3]);
916  RowSeparator<T04>()(out, colsep, widths[ 4]);
917  RowSeparator<T05>()(out, colsep, widths[ 5]);
918  RowSeparator<T06>()(out, colsep, widths[ 6]);
919  RowSeparator<T07>()(out, colsep, widths[ 7]);
920  RowSeparator<T08>()(out, colsep, widths[ 8]);
921  RowSeparator<T09>()(out, colsep, widths[ 9]);
922  RowSeparator<T10>()(out, colsep, widths[10]);
923  RowSeparator<T11>()(out, colsep, widths[11]);
924  RowSeparator<T12>()(out, colsep, widths[12]);
925  RowSeparator<T13>()(out, colsep, widths[13]);
926  RowSeparator<T14>()(out, colsep, widths[14]);
927  RowSeparator<T15>()(out, colsep, widths[15]);
928  out <<"\n";
929  }
930 
932  void
933  print_row(std::ostream &out, const Tuple &t, const std::vector<size_t> &widths) const {
934  FormatRestorer fr(out);
935  out << prefix_ <<std::setw(widths[ 0]) <<render(render_.r0, t.v0, widths[ 0])
936  <<(ColumnTraits<T01>::valid_column ? colsep_ : "") <<std::setw(widths[ 1]) <<render(render_.r1, t.v1, widths[ 1])
937  <<(ColumnTraits<T02>::valid_column ? colsep_ : "") <<std::setw(widths[ 2]) <<render(render_.r2, t.v2, widths[ 2])
938  <<(ColumnTraits<T03>::valid_column ? colsep_ : "") <<std::setw(widths[ 3]) <<render(render_.r3, t.v3, widths[ 3])
939  <<(ColumnTraits<T04>::valid_column ? colsep_ : "") <<std::setw(widths[ 4]) <<render(render_.r4, t.v4, widths[ 4])
940  <<(ColumnTraits<T05>::valid_column ? colsep_ : "") <<std::setw(widths[ 5]) <<render(render_.r5, t.v5, widths[ 5])
941  <<(ColumnTraits<T06>::valid_column ? colsep_ : "") <<std::setw(widths[ 6]) <<render(render_.r6, t.v6, widths[ 6])
942  <<(ColumnTraits<T07>::valid_column ? colsep_ : "") <<std::setw(widths[ 7]) <<render(render_.r7, t.v7, widths[ 7])
943  <<(ColumnTraits<T08>::valid_column ? colsep_ : "") <<std::setw(widths[ 8]) <<render(render_.r8, t.v8, widths[ 8])
944  <<(ColumnTraits<T09>::valid_column ? colsep_ : "") <<std::setw(widths[ 9]) <<render(render_.r9, t.v9, widths[ 9])
945  <<(ColumnTraits<T10>::valid_column ? colsep_ : "") <<std::setw(widths[10]) <<render(render_.r10, t.v10, widths[10])
946  <<(ColumnTraits<T11>::valid_column ? colsep_ : "") <<std::setw(widths[11]) <<render(render_.r11, t.v11, widths[11])
947  <<(ColumnTraits<T12>::valid_column ? colsep_ : "") <<std::setw(widths[12]) <<render(render_.r12, t.v12, widths[12])
948  <<(ColumnTraits<T13>::valid_column ? colsep_ : "") <<std::setw(widths[13]) <<render(render_.r13, t.v13, widths[13])
949  <<(ColumnTraits<T14>::valid_column ? colsep_ : "") <<std::setw(widths[14]) <<render(render_.r14, t.v14, widths[14])
950  <<(ColumnTraits<T15>::valid_column ? colsep_ : "") <<std::setw(widths[15]) <<render(render_.r15, t.v15, widths[15])
951  <<"\n";
952  }
953 
955  void print(std::ostream &out) const {
956  std::vector<size_t> widths = colsizes();
957 
958  // Headers
959  bool has_headers = false;
960  for (size_t i=0; i<MAXCOLS; ++i) {
961  widths[i] = std::max(widths[i], headers_[i].size());
962  if (!headers_[i].empty())
963  has_headers = true;
964  }
965  if (has_headers) {
966  print_headers(out, widths);
967  print_rowsep(out, widths);
968  }
969 
970  // Body
971  if (rows_.empty()) {
972  out <<prefix_ <<"(0 rows)\n\n";
973  } else {
974  for (size_t i=0; i<rows_.size(); ++i) {
975  if (i>0 && has_headers && reprint_headers_>0 && 0==i%reprint_headers_) {
976  print_rowsep(out, widths);
977  print_headers(out, widths);
978  print_rowsep(out, widths);
979  }
980  if (pre_row_)
981  (*pre_row_)(out, this, i, widths);
982  print_row(out, rows_[i], widths);
983  if (post_row_)
984  (*post_row_)(out, this, i, widths);
985  }
986  }
987 
988  // Epilogue
989  if (has_headers && !rows_.empty())
990  print_rowsep(out, widths);
991  }
992 
993 private:
994  std::vector<std::string> headers_;
995  Renderers render_;
996  Rows rows_;
997  std::string colsep_;
998  PrePostRow<Table> *pre_row_, *post_row_;
999  size_t reprint_headers_;
1000  std::string prefix_; // string printed before every line of output
1001 };
1002 
1003 } // namespace
1004 #endif
std::string in(const Container &values)
Converts a container of values to an SQL "in" clause.
Definition: SqlDatabase.h:474
std::vector< Tuple > Rows
All rows of a table.
Definition: SqlDatabase.h:732
Functors for rendering column values.
Definition: SqlDatabase.h:714
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:749
void set_debug(FILE *f)
Debugging property.
size_t size() const
Return the number of rows in the table.
Definition: SqlDatabase.h:802
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:796
Tuple & operator[](size_t i)
Return a reference to a particular row.
Definition: SqlDatabase.h:812
Connection to a database.
Definition: SqlDatabase.h:193
static TransactionPtr create(const ConnectionPtr &conn)
Create a new transaction.
bool empty() const
Returns true if table has no rows.
Definition: SqlDatabase.h:805
std::vector< size_t > colsizes() const
Compute column widths.
Definition: SqlDatabase.h:858
void reprint_headers(size_t nrows)
How often should headers be reprinted?
Definition: SqlDatabase.h:766
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:350
void print(std::ostream &) const
Print some basic info about this transaction.
In-memory representation of a database table.
Definition: SqlDatabase.h:695
A database operation.
Definition: SqlDatabase.h:345
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.
Definition: SqlDatabase.h:146
int execute_int()
Execute a statement that returns a single integer.
std::string format
Format, as for strftime().
Definition: SqlDatabase.h:564
std::string in_strings(const Container &values, Driver driver)
Converts a container of strings to an SQL "in" clause of strings.
Definition: SqlDatabase.h:495
Called before and after printing each row of a table.
Definition: SqlDatabase.h:575
STL namespace.
void clear()
Clear the table by removing all rows.
Definition: SqlDatabase.h:808
TransactionPtr transaction() const
Returns the transaction for this statement.
Renders a column value as a string.
Definition: SqlDatabase.h:524
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:549
void print(std::ostream &) const
Print some basic info about this connection.
Maximum number of columns allowed in a table.
Definition: SqlDatabase.h:698
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:933
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:122
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:820
void header(int colnum, const std::string &hdr)
Headers to use when printing the table.
Definition: SqlDatabase.h:745
iterator end()
Returns an end iterator.
Definition: SqlDatabase.h:399
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:738
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:846
bool local_tz
Use local time zone rather than GMT.
Definition: SqlDatabase.h:563
double execute_double()
Execute a statement that returns a single double.
AddrRenderer addr64Renderer
Renders 64-bit addresses in hexadecimal.
Exceptions thrown by database operations.
Definition: SqlDatabase.h:161
void prepost(PrePostRow< Table > *pre, PrePostRow< Table > *post)
Accessor for functors called before and after each row is printed.
Definition: SqlDatabase.h:792
virtual std::string operator()(const T &value, size_t width) const
Renders a column value as a string.
Definition: SqlDatabase.h:530
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:117
void line_prefix(const std::string &s)
String to print at the beginning of every line of output.
Definition: SqlDatabase.h:840
FILE * get_debug() const
Debugging property.
Renderers & renderers()
Accessor for value renderers.
Definition: SqlDatabase.h:786
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:903
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.
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:552
static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER)
Create a new database connection.
Definition: SqlDatabase.h:203
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:882
Iterates over the result rows.
Definition: SqlDatabase.h:357
const Renderers & renderers() const
Accessor for value renderers.
Definition: SqlDatabase.h:787
void insert(const Tuple &tuple)
Add a new row to the end of the table.
Definition: SqlDatabase.h:819
Used only by the default Connection constructor.
Definition: SqlDatabase.h:121
const Tuple & operator[](size_t i) const
Return a reference to a particular row.
Definition: SqlDatabase.h:813
boost::shared_ptr< Connection > ConnectionPtr
Shared-ownership pointer to a database connection.
Definition: SqlDatabase.h:136
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:487
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:767
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:264
void execute(const std::string &sql)
Execute one or more statements.
One row of a table.
Definition: SqlDatabase.h:702
iterator begin()
Execute this statement.
boost::shared_ptr< Statement > StatementPtr
Shared-ownership pointer to a statement.
Definition: SqlDatabase.h:151
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:841
Renders a time_t as a string.
Definition: SqlDatabase.h:562
Table()
Creates a new, empty table.
Definition: SqlDatabase.h:735
void print(std::ostream &out) const
Print all rows of the table to the specified stream.
Definition: SqlDatabase.h:955
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.
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:753
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:120
void insert(const StatementPtr &stmt)
Insert more rows into a table by running the specified query.
Definition: SqlDatabase.h:829