From 0a71eaad620be004e7e28e7d3265a373dcd92395 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 7 Nov 2011 15:00:06 +0200 Subject: Add support for SQL statement tracing --- odb/sqlite/auto-handle.hxx | 2 +- odb/sqlite/connection.cxx | 4 +- odb/sqlite/connection.hxx | 20 ++++++++++ odb/sqlite/database.hxx | 20 ++++++++++ odb/sqlite/forward.hxx | 2 + odb/sqlite/makefile | 1 + odb/sqlite/statement-cache.cxx | 10 ++--- odb/sqlite/statement-cache.hxx | 20 +++++----- odb/sqlite/statement.cxx | 86 ++++++++++++++++++++++++++++++++++++++---- odb/sqlite/statement.hxx | 25 ++++++------ odb/sqlite/tracer.cxx | 62 ++++++++++++++++++++++++++++++ odb/sqlite/tracer.hxx | 62 ++++++++++++++++++++++++++++++ odb/sqlite/transaction.hxx | 20 ++++++++++ 13 files changed, 296 insertions(+), 38 deletions(-) create mode 100644 odb/sqlite/tracer.cxx create mode 100644 odb/sqlite/tracer.hxx (limited to 'odb') diff --git a/odb/sqlite/auto-handle.hxx b/odb/sqlite/auto-handle.hxx index 60b1ea9..f0f0806 100644 --- a/odb/sqlite/auto-handle.hxx +++ b/odb/sqlite/auto-handle.hxx @@ -83,7 +83,7 @@ namespace odb return h; } - operator H* () + operator H* () const { return h_; } diff --git a/odb/sqlite/connection.cxx b/odb/sqlite/connection.cxx index 7b16547..f9753be 100644 --- a/odb/sqlite/connection.cxx +++ b/odb/sqlite/connection.cxx @@ -80,7 +80,7 @@ namespace odb { // Enable/disable foreign key constraints. // - simple_statement st ( + generic_statement st ( *this, db_.foreign_keys () ? "PRAGMA foreign_keys=ON" @@ -122,7 +122,7 @@ namespace odb unsigned long long connection:: execute (const char* s, std::size_t n) { - simple_statement st (*this, s, n); + generic_statement st (*this, s, n); return st.execute (); } diff --git a/odb/sqlite/connection.hxx b/odb/sqlite/connection.hxx index 4ad4f42..0986866 100644 --- a/odb/sqlite/connection.hxx +++ b/odb/sqlite/connection.hxx @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -69,6 +70,25 @@ namespace odb virtual unsigned long long execute (const char* statement, std::size_t length); + // SQL statement tracing. + // + public: + typedef sqlite::tracer tracer_type; + + void + tracer (tracer_type& t) + { + odb::connection::tracer (t); + } + + void + tracer (tracer_type* t) + { + odb::connection::tracer (t); + } + + using odb::connection::tracer; + public: sqlite3* handle () diff --git a/odb/sqlite/database.hxx b/odb/sqlite/database.hxx index 348f236..aeaca22 100644 --- a/odb/sqlite/database.hxx +++ b/odb/sqlite/database.hxx @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -100,6 +101,25 @@ namespace odb connection_ptr connection (); + // SQL statement tracing. + // + public: + typedef sqlite::tracer tracer_type; + + void + tracer (tracer_type& t) + { + odb::database::tracer (t); + } + + void + tracer (tracer_type* t) + { + odb::database::tracer (t); + } + + using odb::database::tracer; + public: virtual ~database (); diff --git a/odb/sqlite/forward.hxx b/odb/sqlite/forward.hxx index cc1fbfc..5ad3a0f 100644 --- a/odb/sqlite/forward.hxx +++ b/odb/sqlite/forward.hxx @@ -18,7 +18,9 @@ namespace odb class connection; typedef details::shared_ptr connection_ptr; class connection_factory; + class statement; class transaction; + class tracer; class query; // Implementation details. diff --git a/odb/sqlite/makefile b/odb/sqlite/makefile index 50ef959..69ae8de 100644 --- a/odb/sqlite/makefile +++ b/odb/sqlite/makefile @@ -18,6 +18,7 @@ result.cxx \ statement-cache.cxx \ statement.cxx \ statements-base.cxx \ +tracer.cxx \ traits.cxx \ transaction.cxx \ transaction-impl.cxx diff --git a/odb/sqlite/statement-cache.cxx b/odb/sqlite/statement-cache.cxx index ba7b56c..48a4220 100644 --- a/odb/sqlite/statement-cache.cxx +++ b/odb/sqlite/statement-cache.cxx @@ -17,9 +17,9 @@ namespace odb // String lengths below include '\0', as per SQLite manual // suggestions. // - begin_ (new (shared) simple_statement (conn_, "BEGIN", 6)), - commit_ (new (shared) simple_statement (conn_, "COMMIT", 7)), - rollback_ (new (shared) simple_statement (conn_, "ROLLBACK", 9)) + begin_ (new (shared) generic_statement (conn_, "BEGIN", 6)), + commit_ (new (shared) generic_statement (conn_, "COMMIT", 7)), + rollback_ (new (shared) generic_statement (conn_, "ROLLBACK", 9)) { rollback_->cached (true); commit_->cached (true); @@ -30,7 +30,7 @@ namespace odb begin_immediate_statement_ () const { begin_immediate_.reset ( - new (shared) simple_statement (conn_, "BEGIN IMMEDIATE", 16)); + new (shared) generic_statement (conn_, "BEGIN IMMEDIATE", 16)); begin_immediate_->cached (true); } @@ -38,7 +38,7 @@ namespace odb begin_exclusive_statement_ () const { begin_exclusive_.reset ( - new (shared) simple_statement (conn_, "BEGIN EXCLUSIVE", 16)); + new (shared) generic_statement (conn_, "BEGIN EXCLUSIVE", 16)); begin_exclusive_->cached (true); } } diff --git a/odb/sqlite/statement-cache.hxx b/odb/sqlite/statement-cache.hxx index 1bdefb6..4f717e7 100644 --- a/odb/sqlite/statement-cache.hxx +++ b/odb/sqlite/statement-cache.hxx @@ -35,13 +35,13 @@ namespace odb public: statement_cache (connection&); - simple_statement& + generic_statement& begin_statement () const { return *begin_; } - simple_statement& + generic_statement& begin_immediate_statement () const { if (!begin_immediate_) @@ -50,7 +50,7 @@ namespace odb return *begin_immediate_; } - simple_statement& + generic_statement& begin_exclusive_statement () const { if (!begin_exclusive_) @@ -59,13 +59,13 @@ namespace odb return *begin_exclusive_; } - simple_statement& + generic_statement& commit_statement () const { return *commit_; } - simple_statement& + generic_statement& rollback_statement () const { return *rollback_; @@ -119,11 +119,11 @@ namespace odb connection& conn_; - details::shared_ptr begin_; - mutable details::shared_ptr begin_immediate_; - mutable details::shared_ptr begin_exclusive_; - details::shared_ptr commit_; - details::shared_ptr rollback_; + details::shared_ptr begin_; + mutable details::shared_ptr begin_immediate_; + mutable details::shared_ptr begin_exclusive_; + details::shared_ptr commit_; + details::shared_ptr rollback_; map map_; }; diff --git a/odb/sqlite/statement.cxx b/odb/sqlite/statement.cxx index a33ebcb..e1f4fb6 100644 --- a/odb/sqlite/statement.cxx +++ b/odb/sqlite/statement.cxx @@ -6,8 +6,10 @@ #include // std::memcpy #include +#include #include // object_not_persistent +#include #include #include #include @@ -24,7 +26,8 @@ namespace odb statement:: ~statement () { - finilize (); + if (stmt_ != 0) + finilize (); } void statement:: @@ -53,6 +56,35 @@ namespace odb next_ = this; list_add (); // Add to the list because we are uncached. + + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->prepare (conn_, *this); + } + } + + void statement:: + finilize () + { + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->deallocate (conn_, *this); + } + + list_remove (); + stmt_.reset (); + } + + const char* statement:: + text () const + { + return sqlite3_sql (stmt_); } void statement:: @@ -187,29 +219,37 @@ namespace odb return r; } - // simple_statement + // generic_statement // - simple_statement:: - simple_statement (connection& conn, const string& s) + generic_statement:: + generic_statement (connection& conn, const string& s) : statement (conn, s), result_set_ (stmt_ ? sqlite3_column_count (stmt_) != 0: false) { } - simple_statement:: - simple_statement (connection& conn, const char* s, std::size_t n) + generic_statement:: + generic_statement (connection& conn, const char* s, std::size_t n) : statement (conn, s, n), result_set_ (stmt_ ? sqlite3_column_count (stmt_) != 0: false) { } - unsigned long long simple_statement:: + unsigned long long generic_statement:: execute () { if (stmt_ == 0) // Empty statement or comment. return 0; + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + unsigned long long r (0); // Only the first call to sqlite3_step() can return SQLITE_LOCKED. @@ -266,6 +306,14 @@ namespace odb if (active ()) reset (); + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + done_ = false; if (param_ != 0) @@ -340,6 +388,14 @@ namespace odb bool insert_statement:: execute () { + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + bind_param (param_.bind, param_.count); int e; @@ -392,6 +448,14 @@ namespace odb unsigned long long update_statement:: execute () { + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + bind_param (param_.bind, param_.count); int e; @@ -426,6 +490,14 @@ namespace odb unsigned long long delete_statement:: execute () { + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + bind_param (param_.bind, param_.count); int e; diff --git a/odb/sqlite/statement.hxx b/odb/sqlite/statement.hxx index 4fad1a3..4f1e3fd 100644 --- a/odb/sqlite/statement.hxx +++ b/odb/sqlite/statement.hxx @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -30,18 +30,21 @@ namespace odb { class connection; - class LIBODB_SQLITE_EXPORT statement: public details::shared_base + class LIBODB_SQLITE_EXPORT statement: public odb::statement { public: virtual ~statement () = 0; sqlite3_stmt* - handle () + handle () const { return stmt_; } + virtual const char* + text () const; + // Cached state (public part). // public: @@ -130,11 +133,7 @@ namespace odb // protected: void - finilize () - { - list_remove (); - stmt_.reset (); - } + finilize (); protected: friend class connection; @@ -191,18 +190,18 @@ namespace odb statement* next_; }; - class LIBODB_SQLITE_EXPORT simple_statement: public statement + class LIBODB_SQLITE_EXPORT generic_statement: public statement { public: - simple_statement (connection&, const std::string& statement); - simple_statement (connection&, const char* statement, std::size_t n); + generic_statement (connection&, const std::string& statement); + generic_statement (connection&, const char* statement, std::size_t n); unsigned long long execute (); private: - simple_statement (const simple_statement&); - simple_statement& operator= (const simple_statement&); + generic_statement (const generic_statement&); + generic_statement& operator= (const generic_statement&); private: bool result_set_; diff --git a/odb/sqlite/tracer.cxx b/odb/sqlite/tracer.cxx new file mode 100644 index 0000000..45f1a3d --- /dev/null +++ b/odb/sqlite/tracer.cxx @@ -0,0 +1,62 @@ +// file : odb/sqlite/tracer.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +namespace odb +{ + namespace sqlite + { + tracer:: + ~tracer () + { + } + + void tracer:: + prepare (connection&, const statement&) + { + } + + void tracer:: + execute (connection& c, const statement& s) + { + execute (c, s.text ()); + } + + void tracer:: + deallocate (connection&, const statement&) + { + } + + void tracer:: + prepare (odb::connection& c, const odb::statement& s) + { + prepare (static_cast (c), + static_cast (s)); + } + + void tracer:: + execute (odb::connection& c, const odb::statement& s) + { + execute (static_cast (c), + static_cast (s)); + } + + void tracer:: + execute (odb::connection& c, const char* s) + { + execute (static_cast (c), s); + } + + void tracer:: + deallocate (odb::connection& c, const odb::statement& s) + { + deallocate (static_cast (c), + static_cast (s)); + } + } +} diff --git a/odb/sqlite/tracer.hxx b/odb/sqlite/tracer.hxx new file mode 100644 index 0000000..f5466dc --- /dev/null +++ b/odb/sqlite/tracer.hxx @@ -0,0 +1,62 @@ +// file : odb/sqlite/tracer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SQLITE_TRACER_HXX +#define ODB_SQLITE_TRACER_HXX + +#include + +#include + +#include +#include + +namespace odb +{ + namespace sqlite + { + class LIBODB_EXPORT tracer: private odb::tracer + { + public: + virtual + ~tracer (); + + virtual void + prepare (connection&, const statement&); + + virtual void + execute (connection&, const statement&); + + virtual void + execute (connection&, const char* statement) = 0; + + virtual void + deallocate (connection&, const statement&); + + private: + // Allow these classes to convert sqlite::tracer to odb::tracer. + // + friend class database; + friend class connection; + friend class transaction; + + virtual void + prepare (odb::connection&, const odb::statement&); + + virtual void + execute (odb::connection&, const odb::statement&); + + virtual void + execute (odb::connection&, const char* statement); + + virtual void + deallocate (odb::connection&, const odb::statement&); + }; + } +} + +#include + +#endif // ODB_SQLITE_TRACER_HXX diff --git a/odb/sqlite/transaction.hxx b/odb/sqlite/transaction.hxx index b30a818..dbf73ab 100644 --- a/odb/sqlite/transaction.hxx +++ b/odb/sqlite/transaction.hxx @@ -12,6 +12,7 @@ #include #include +#include #include namespace odb @@ -50,6 +51,25 @@ namespace odb static void current (transaction&); + // SQL statement tracing. + // + public: + typedef sqlite::tracer tracer_type; + + void + tracer (tracer_type& t) + { + odb::transaction::tracer (t); + } + + void + tracer (tracer_type* t) + { + odb::transaction::tracer (t); + } + + using odb::transaction::tracer; + public: transaction_impl& implementation (); -- cgit v1.1