ROSE  0.11.54.0
SqlDatabase.h
1 #ifndef ROSE_SqlDatabase_H
2 #define ROSE_SqlDatabase_H
3 
4 #include <Rose/FormatRestorer.h>
5 #include "Rose/Exception.h"
6 #include <Rose/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:
196  typedef std::pair<std::string /*name*/, std::string /*value*/> Parameter;
197 
199  struct ParsedUrl {
200  Driver driver; // database low-level driver
201  std::string dbName; // main part of URL -- database name or maybe a file name
202  std::vector<Parameter> params; // stuff after the last "?"
203  std::string error; // error message if there was a problem parsing
204 
205  ParsedUrl()
206  : driver(NO_DRIVER) {}
207  };
208 
214  static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER) {
215  if (NO_DRIVER==driver) {
216  if (NO_DRIVER==(driver = guess_driver(open_spec)))
217  throw Exception("no suitable driver for \""+open_spec+"\"");
218  }
219  return ConnectionPtr(new Connection(open_spec, driver));
220  }
221 
225  TransactionPtr transaction();
226 
229  static Driver guess_driver(const std::string &open_spec);
230 
232  Driver driver() const;
233 
235  std::string openspec() const;
236 
240  void set_debug(FILE *f);
241  FILE *get_debug() const;
245  void print(std::ostream&) const;
246 
247  // Only called by boost::shared_ptr
248  ~Connection() { finish(); }
249 
251  static std::string connectionSpecification(const std::string &uri, Driver driver = NO_DRIVER);
252 
254  static ParsedUrl parseUrl(std::string url);
255 
256 protected:
257  // Protected because you should be using create() to get a smart pointer. Database driver-level connections are typically
258  // not copyable object anyway.
259  Connection(const std::string &open_spec, Driver driver): impl(NULL) { init(open_spec, driver); }
260 
261 private:
262  void init(const std::string &open_spec, Driver driver);
263  void finish();
264 
265 private:
266  ConnectionImpl *impl;
267 };
268 
269 /*******************************************************************************************************************************
270  * Transactions
271  *******************************************************************************************************************************/
272 
278 class Transaction: public boost::enable_shared_from_this<Transaction> {
279  friend class ConnectionImpl;
280  friend class Statement;
281  friend class StatementImpl;
282 public:
286  static TransactionPtr create(const ConnectionPtr &conn);
287 
291  void rollback();
292 
296  void commit();
297 
300  bool is_terminated() const;
301 
303  StatementPtr statement(const std::string &sql);
304 
308  void execute(const std::string &sql);
309 
313  void bulk_load(const std::string &tablename, std::istream&);
314 
316  Driver driver() const;
317 
319  ConnectionPtr connection() const;
320 
325  void set_debug(FILE *f);
326  FILE *get_debug() const;
330  void print(std::ostream&) const;
331 
332  // Only called by boost::shared_ptr
333  ~Transaction() { finish(); }
334 
335 protected:
336  explicit Transaction(const ConnectionPtr &conn, size_t drv_conn): impl(NULL) { init(conn, drv_conn); }
337 
338 private:
339  void init(const ConnectionPtr &conn, size_t drv_conn);
340  void finish();
341 
342 private:
343  TransactionImpl *impl;
344 };
345 
346 
347 /*******************************************************************************************************************************
348  * Statements
349  *******************************************************************************************************************************/
350 
359 class Statement: public boost::enable_shared_from_this<Statement> {
360 public:
361 
364  static StatementPtr create(const TransactionPtr &tranx, const std::string &sql) {
365  return StatementPtr(new Statement(tranx, sql));
366  }
367 
371  class iterator {
372  public:
373  iterator(): execution_seq(0), row_num(0) { init(); } // an end iterator
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);
384  iterator& operator++();
385  bool at_eof() const;
386  bool operator==(const iterator &other) const;
387  bool operator!=(const iterator &other) const { return !(*this==other); }
388  private:
389  void init();
390  void check() const; // check that this iterator is not stale
391  private:
392  StatementPtr stmt; // statement whose results we are iterating over
393  size_t execution_seq; // statement execution counter
394  size_t row_num; // row number
395  };
396 
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);
408  StatementPtr bind_null(size_t idx);
412  iterator begin();
413 
416  iterator end() { return iterator(); }
417 
419  void execute();
420 
422  int execute_int();
423 
425  double execute_double();
426 
428  std::string execute_string();
429 
431  std::vector<uint8_t> execute_blob();
432 
434  Driver driver() const;
435 
437  TransactionPtr transaction() const;
438 
443  void set_debug(FILE *f);
444  FILE *get_debug() const;
448  void print(std::ostream&) const;
449 
450 public:
451  // Called only by boost::shared_ptr
452  ~Statement() { finish(); }
453 
454 protected:
455  Statement(const TransactionPtr &tranx, const std::string &sql): impl(NULL) { init(tranx, sql); }
456 
457 private:
458  void init(const TransactionPtr &tranx, const std::string &sql);
459  void finish();
460 
461 private:
462  StatementImpl *impl;
463 };
464 
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);
473 
474 /*******************************************************************************************************************************
475  * Miscellaneous functions
476  *******************************************************************************************************************************/
477 
479 std::string uriDocumentation();
480 
482 std::vector<std::string> split_sql(const std::string &sql);
483 
485 std::string escape(const std::string&, Driver, bool do_quote=true);
486 
488 std::string hexSequence(const std::vector<uint8_t> &v, Driver driver);
489 
491 bool is_valid_table_name(const std::string &name);
492 
494 template<class Container>
495 std::string in(const Container &values)
496 {
497  std::ostringstream retval;
498  retval <<"in (";
499  unsigned nvals = 0;
500  for (typename Container::const_iterator vi=values.begin(); vi!=values.end(); ++vi, ++nvals)
501  retval <<(nvals?", ":"") <<*vi;
502  retval <<")";
503  return retval.str();
504 }
505 
507 template<class Container, class Stringifier>
508 std::string in_numbers(const Container &values, Stringifier &stringifier)
509 {
510  return "in (" + Rose::StringUtility::join(", ", Rose::StringUtility::toStrings(values, stringifier)) + ")";
511 }
512 
515 template<class Container>
516 std::string in_strings(const Container &values, Driver driver)
517 {
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));
521  return in(strings);
522 }
523 
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&);
529 
530 /*******************************************************************************************************************************
531  * Tables
532  *******************************************************************************************************************************/
533 
534 // The things here that don't have doxygen comments are not intended to be used directly by users.
535 
536 template<typename> struct ColumnTraits {
537  enum { valid_column = 1 };
538 };
539 template<> struct ColumnTraits<NoColumn> {
540  enum { valid_column = 0 };
541 };
542 
544 template<typename T>
545 class Renderer {
546 public:
547  virtual ~Renderer() {}
548 
551  virtual std::string operator()(const T &value, size_t width) const {
552  std::ostringstream ss;
553  ss <<value;
554  return ss.str();
555  }
556 };
557 
558 // Specialized for string-valued columns in order to left-justify the string by padding it on the right with an
559 // appropriate number of SPC characters.
560 template<>
561 class Renderer<std::string> {
562 public:
563  virtual ~Renderer() {}
564  virtual std::string operator()(const std::string &value, size_t width) const {
565  return value + std::string(width, ' ');
566  }
567 };
568 
570 struct AddrRenderer: Renderer<uint64_t> {
571  size_t nbits; // number of bits in addresses; higher addresses will result in more digits
572  explicit AddrRenderer(size_t nbits=32): nbits(nbits) {}
573  virtual std::string operator()(const uint64_t &value, size_t width) const ROSE_OVERRIDE {
574  return Rose::StringUtility::addrToString(value, nbits);
575  }
576 };
577 extern AddrRenderer addr8Renderer;
578 extern AddrRenderer addr16Renderer;
579 extern AddrRenderer addr32Renderer;
580 extern AddrRenderer addr64Renderer;
583 struct TimeRenderer: Renderer<time_t> {
584  bool local_tz;
585  std::string format;
586  TimeRenderer(): local_tz(true), format("%F %T %z") {}
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;
589 };
590 extern TimeRenderer timeRenderer;
591 extern TimeRenderer dateRenderer;
592 extern TimeRenderer humanTimeRenderer;
595 template<typename Table>
596 class PrePostRow {
597 public:
598  virtual ~PrePostRow() {}
599  virtual void operator()(std::ostream &out, const Table *table, size_t rownum, const std::vector<size_t> &widths) {}
600 };
601 
602 // Prints a header
603 template<typename T>
604 class Header {
605 public:
606  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {
607  FormatRestorer fr(out);
608  out <<prefix <<std::setw(width) <<hdr;
609  }
610 };
611 template<>
612 class Header<std::string> {
613 public:
614  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {
615  FormatRestorer fr(out);
616  out <<prefix <<std::setw(width) <<std::left <<hdr;
617  }
618 };
619 template<>
620 class Header<NoColumn> {
621 public:
622  void operator()(std::ostream &out, const std::string &prefix, const std::string &hdr, size_t width) {}
623 };
624 
625 // Prints a row separator for a single column
626 template<typename T>
628 public:
629  void operator()(std::ostream &out, const std::string &prefix, size_t width) {
630  out <<prefix <<std::string(width, '-');
631  }
632 };
633 template<>
635 public:
636  void operator()(std::ostream &out, const std::string &prefix, size_t width) {}
637 };
638 
712 template<typename T00, typename T01=NoColumn, typename T02=NoColumn, typename T03=NoColumn,
713  typename T04=NoColumn, typename T05=NoColumn, typename T06=NoColumn, typename T07=NoColumn,
714  typename T08=NoColumn, typename T09=NoColumn, typename T10=NoColumn, typename T11=NoColumn,
715  typename T12=NoColumn, typename T13=NoColumn, typename T14=NoColumn, typename T15=NoColumn>
716 class Table {
717 public:
718  enum {
719  MAXCOLS=16,
720  };
721 
723  struct Tuple { // We could use boost::tuple, but it has a 10-member limit.
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;
732  };
733 
735  struct Renderers { // We could use boost::tuple, but it has a 10-member limit.
736  explicit Renderers(const Renderer<T00> *r0 =NULL, const Renderer<T01> *r1 =NULL,
737  const Renderer<T02> *r2 =NULL, const Renderer<T03> *r3 =NULL,
738  const Renderer<T04> *r4 =NULL, const Renderer<T05> *r5 =NULL,
739  const Renderer<T06> *r6 =NULL, const Renderer<T07> *r7 =NULL,
740  const Renderer<T08> *r8 =NULL, const Renderer<T09> *r9 =NULL,
741  const Renderer<T10> *r10=NULL, const Renderer<T11> *r11=NULL,
742  const Renderer<T12> *r12=NULL, const Renderer<T13> *r13=NULL,
743  const Renderer<T14> *r14=NULL, const Renderer<T15> *r15=NULL)
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) {}
746  const Renderer<T00> *r0; const Renderer<T01> *r1; const Renderer<T02> *r2; const Renderer<T03> *r3;
747  const Renderer<T04> *r4; const Renderer<T05> *r5; const Renderer<T06> *r6; const Renderer<T07> *r7;
748  const Renderer<T08> *r8; const Renderer<T09> *r9; const Renderer<T10> *r10; const Renderer<T11> *r11;
749  const Renderer<T12> *r12; const Renderer<T13> *r13; const Renderer<T14> *r14; const Renderer<T15> *r15;
750  };
751 
753  typedef std::vector<Tuple> Rows;
754 
756  Table(): headers_(MAXCOLS), colsep_(" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {}
757 
759  explicit Table(const StatementPtr &stmt)
760  : headers_(MAXCOLS), colsep_(" | "), pre_row_(NULL), post_row_(NULL), reprint_headers_(0) {
761  insert(stmt);
762  }
763 
766  void header(int colnum, const std::string &hdr) {
767  assert(colnum<headers_.size());
768  headers_[colnum] = hdr;
769  }
770  const std::string& header(int colnum) const {
771  assert(colnum<headers_.size());
772  return headers_[colnum];
773  }
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;
782  }
787  void reprint_headers(size_t nrows) { reprint_headers_ = nrows; }
788  size_t reprint_headers() const { return reprint_headers_; }
807  Renderers& renderers() { return render_; }
808  const Renderers& renderers() const { return render_; }
814  pre_row_ = pre;
815  post_row_ = post;
816  }
817  std::pair<PrePostRow<Table>*, PrePostRow<Table>*> prepost() const {
818  return std::make_pair(pre_row_, post_row_);
819  }
823  size_t size() const { return rows_.size(); }
824 
826  bool empty() const { return rows_.empty(); }
827 
829  void clear() { rows_.clear(); }
830 
833  Tuple& operator[](size_t i) { assert(i<rows_.size()); return rows_[i]; }
834  const Tuple& operator[](size_t i) const { assert(i<rows_.size()); return rows_[i]; }
840  void insert(const Tuple &tuple) { rows_.push_back(tuple); }
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));
846  }
850  void insert(const StatementPtr &stmt) {
851  for (Statement::iterator row=stmt->begin(); row!=stmt->end(); ++row) {
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)));
856  }
857  }
858 
861  void line_prefix(const std::string &s) { prefix_ = s; }
862  const std::string& line_prefix() const { return prefix_; }
866  template<typename T>
867  std::string render(const Renderer<T> *r, const T &value, size_t width=0) const {
868  Renderer<T> r_;
869  if (NULL==r)
870  r = &r_;
871  std::string s = (*r)(value, width);
872  if (width!=0)
873  s = s.substr(0, width);
874  return s;
875  }
876 
879  std::vector<size_t> colsizes() const {
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());
898  }
899  return widths;
900  }
901 
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]);
920  out <<"\n";
921  }
922 
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])) {
928  colsep[i] = '-';
929  } else if ('|'==colsep[i]) {
930  colsep[i] = '+';
931  }
932  }
933  RowSeparator<T00>()(out, prefix_, widths[ 0]);
934  RowSeparator<T01>()(out, colsep, widths[ 1]);
935  RowSeparator<T02>()(out, colsep, widths[ 2]);
936  RowSeparator<T03>()(out, colsep, widths[ 3]);
937  RowSeparator<T04>()(out, colsep, widths[ 4]);
938  RowSeparator<T05>()(out, colsep, widths[ 5]);
939  RowSeparator<T06>()(out, colsep, widths[ 6]);
940  RowSeparator<T07>()(out, colsep, widths[ 7]);
941  RowSeparator<T08>()(out, colsep, widths[ 8]);
942  RowSeparator<T09>()(out, colsep, widths[ 9]);
943  RowSeparator<T10>()(out, colsep, widths[10]);
944  RowSeparator<T11>()(out, colsep, widths[11]);
945  RowSeparator<T12>()(out, colsep, widths[12]);
946  RowSeparator<T13>()(out, colsep, widths[13]);
947  RowSeparator<T14>()(out, colsep, widths[14]);
948  RowSeparator<T15>()(out, colsep, widths[15]);
949  out <<"\n";
950  }
951 
953  void
954  print_row(std::ostream &out, const Tuple &t, const std::vector<size_t> &widths) const {
955  FormatRestorer fr(out);
956  out << prefix_ <<std::setw(widths[ 0]) <<render(render_.r0, t.v0, widths[ 0])
957  <<(ColumnTraits<T01>::valid_column ? colsep_ : "") <<std::setw(widths[ 1]) <<render(render_.r1, t.v1, widths[ 1])
958  <<(ColumnTraits<T02>::valid_column ? colsep_ : "") <<std::setw(widths[ 2]) <<render(render_.r2, t.v2, widths[ 2])
959  <<(ColumnTraits<T03>::valid_column ? colsep_ : "") <<std::setw(widths[ 3]) <<render(render_.r3, t.v3, widths[ 3])
960  <<(ColumnTraits<T04>::valid_column ? colsep_ : "") <<std::setw(widths[ 4]) <<render(render_.r4, t.v4, widths[ 4])
961  <<(ColumnTraits<T05>::valid_column ? colsep_ : "") <<std::setw(widths[ 5]) <<render(render_.r5, t.v5, widths[ 5])
962  <<(ColumnTraits<T06>::valid_column ? colsep_ : "") <<std::setw(widths[ 6]) <<render(render_.r6, t.v6, widths[ 6])
963  <<(ColumnTraits<T07>::valid_column ? colsep_ : "") <<std::setw(widths[ 7]) <<render(render_.r7, t.v7, widths[ 7])
964  <<(ColumnTraits<T08>::valid_column ? colsep_ : "") <<std::setw(widths[ 8]) <<render(render_.r8, t.v8, widths[ 8])
965  <<(ColumnTraits<T09>::valid_column ? colsep_ : "") <<std::setw(widths[ 9]) <<render(render_.r9, t.v9, widths[ 9])
966  <<(ColumnTraits<T10>::valid_column ? colsep_ : "") <<std::setw(widths[10]) <<render(render_.r10, t.v10, widths[10])
967  <<(ColumnTraits<T11>::valid_column ? colsep_ : "") <<std::setw(widths[11]) <<render(render_.r11, t.v11, widths[11])
968  <<(ColumnTraits<T12>::valid_column ? colsep_ : "") <<std::setw(widths[12]) <<render(render_.r12, t.v12, widths[12])
969  <<(ColumnTraits<T13>::valid_column ? colsep_ : "") <<std::setw(widths[13]) <<render(render_.r13, t.v13, widths[13])
970  <<(ColumnTraits<T14>::valid_column ? colsep_ : "") <<std::setw(widths[14]) <<render(render_.r14, t.v14, widths[14])
971  <<(ColumnTraits<T15>::valid_column ? colsep_ : "") <<std::setw(widths[15]) <<render(render_.r15, t.v15, widths[15])
972  <<"\n";
973  }
974 
976  void print(std::ostream &out) const {
977  std::vector<size_t> widths = colsizes();
978 
979  // Headers
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())
984  has_headers = true;
985  }
986  if (has_headers) {
987  print_headers(out, widths);
988  print_rowsep(out, widths);
989  }
990 
991  // Body
992  if (rows_.empty()) {
993  out <<prefix_ <<"(0 rows)\n\n";
994  } else {
995  for (size_t i=0; i<rows_.size(); ++i) {
996  if (i>0 && has_headers && reprint_headers_>0 && 0==i%reprint_headers_) {
997  print_rowsep(out, widths);
998  print_headers(out, widths);
999  print_rowsep(out, widths);
1000  }
1001  if (pre_row_)
1002  (*pre_row_)(out, this, i, widths);
1003  print_row(out, rows_[i], widths);
1004  if (post_row_)
1005  (*post_row_)(out, this, i, widths);
1006  }
1007  }
1008 
1009  // Epilogue
1010  if (has_headers && !rows_.empty())
1011  print_rowsep(out, widths);
1012  }
1013 
1014 private:
1015  std::vector<std::string> headers_;
1016  Renderers render_;
1017  Rows rows_;
1018  std::string colsep_;
1019  PrePostRow<Table> *pre_row_, *post_row_;
1020  size_t reprint_headers_;
1021  std::string prefix_; // string printed before every line of output
1022 };
1023 
1024 } // namespace
1025 #endif
Broken-out info about a URL.
Definition: SqlDatabase.h:199
std::string in(const Container &values)
Converts a container of values to an SQL "in" clause.
Definition: SqlDatabase.h:495
std::vector< Tuple > Rows
All rows of a table.
Definition: SqlDatabase.h:753
Functors for rendering column values.
Definition: SqlDatabase.h:735
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:770
void set_debug(FILE *f)
Debugging property.
size_t size() const
Return the number of rows in the table.
Definition: SqlDatabase.h:823
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:817
Tuple & operator[](size_t i)
Return a reference to a particular row.
Definition: SqlDatabase.h:833
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:826
std::vector< size_t > colsizes() const
Compute column widths.
Definition: SqlDatabase.h:879
void reprint_headers(size_t nrows)
How often should headers be reprinted?
Definition: SqlDatabase.h:787
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:364
void print(std::ostream &) const
Print some basic info about this transaction.
In-memory representation of a database table.
Definition: SqlDatabase.h:716
A database operation.
Definition: SqlDatabase.h:359
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:147
int execute_int()
Execute a statement that returns a single integer.
std::string format
Format, as for strftime().
Definition: SqlDatabase.h:585
std::string in_strings(const Container &values, Driver driver)
Converts a container of strings to an SQL "in" clause of strings.
Definition: SqlDatabase.h:516
Called before and after printing each row of a table.
Definition: SqlDatabase.h:596
STL namespace.
void clear()
Clear the table by removing all rows.
Definition: SqlDatabase.h:829
TransactionPtr transaction() const
Returns the transaction for this statement.
Renders a column value as a string.
Definition: SqlDatabase.h:545
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:570
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.
Definition: SqlDatabase.h:954
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:841
void header(int colnum, const std::string &hdr)
Headers to use when printing the table.
Definition: SqlDatabase.h:766
iterator end()
Returns an end iterator.
Definition: SqlDatabase.h:416
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:759
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:867
bool local_tz
Use local time zone rather than GMT.
Definition: SqlDatabase.h:584
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:813
virtual std::string operator()(const T &value, size_t width) const
Renders a column value as a string.
Definition: SqlDatabase.h:551
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:861
FILE * get_debug() const
Debugging property.
Renderers & renderers()
Accessor for value renderers.
Definition: SqlDatabase.h:807
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:924
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:573
static ConnectionPtr create(const std::string &open_spec, Driver driver=NO_DRIVER)
Create a new database connection.
Definition: SqlDatabase.h:214
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:903
Iterates over the result rows.
Definition: SqlDatabase.h:371
const Renderers & renderers() const
Accessor for value renderers.
Definition: SqlDatabase.h:808
void insert(const Tuple &tuple)
Add a new row to the end of the table.
Definition: SqlDatabase.h:840
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:834
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:508
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.
Definition: SplitJoin.h:61
size_t reprint_headers() const
How often should headers be reprinted?
Definition: SqlDatabase.h:788
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:278
void execute(const std::string &sql)
Execute one or more statements.
One row of a table.
Definition: SqlDatabase.h:723
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:862
Renders a time_t as a string.
Definition: SqlDatabase.h:583
Table()
Creates a new, empty table.
Definition: SqlDatabase.h:756
void print(std::ostream &out) const
Print all rows of the table to the specified stream.
Definition: SqlDatabase.h:976
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.
Definition: SqlDatabase.h:719
FILE * get_debug() const
Debugging property.
Base class for all ROSE exceptions.
Definition: Rose/Exception.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:774
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:850