From 0e37272b9ab8f37ad2f3d37bf6a09c68e5117d02 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/pgsql/auto-handle.hxx | 2 +- odb/pgsql/connection.cxx | 8 ++++++ odb/pgsql/connection.hxx | 20 ++++++++++++++ odb/pgsql/database.hxx | 20 ++++++++++++++ odb/pgsql/forward.hxx | 2 ++ odb/pgsql/makefile | 1 + odb/pgsql/statement.cxx | 61 +++++++++++++++++++++++++++++++++++++++-- odb/pgsql/statement.hxx | 17 ++++++++++-- odb/pgsql/tracer.cxx | 62 ++++++++++++++++++++++++++++++++++++++++++ odb/pgsql/tracer.hxx | 62 ++++++++++++++++++++++++++++++++++++++++++ odb/pgsql/transaction-impl.cxx | 20 ++++++++++++++ odb/pgsql/transaction.hxx | 20 ++++++++++++++ 12 files changed, 289 insertions(+), 6 deletions(-) create mode 100644 odb/pgsql/tracer.cxx create mode 100644 odb/pgsql/tracer.hxx diff --git a/odb/pgsql/auto-handle.hxx b/odb/pgsql/auto-handle.hxx index 2ed58e5..be565e5 100644 --- a/odb/pgsql/auto-handle.hxx +++ b/odb/pgsql/auto-handle.hxx @@ -72,7 +72,7 @@ namespace odb return h; } - operator H* () + operator H* () const { return h_; } diff --git a/odb/pgsql/connection.cxx b/odb/pgsql/connection.cxx index 6f0feaf..b173136 100644 --- a/odb/pgsql/connection.cxx +++ b/odb/pgsql/connection.cxx @@ -86,6 +86,14 @@ namespace odb // string str (s, n); + { + odb::tracer* t; + if ((t = transaction_tracer ()) || + (t = tracer ()) || + (t = database ().tracer ())) + t->execute (*this, str.c_str ()); + } + auto_handle h (PQexec (handle_, str.c_str ())); unsigned long long count (0); diff --git a/odb/pgsql/connection.hxx b/odb/pgsql/connection.hxx index e8a1f17..737551d 100644 --- a/odb/pgsql/connection.hxx +++ b/odb/pgsql/connection.hxx @@ -18,6 +18,7 @@ #include #include +#include #include #include #include // PGconn @@ -62,6 +63,25 @@ namespace odb virtual unsigned long long execute (const char* statement, std::size_t length); + // SQL statement tracing. + // + public: + typedef pgsql::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: PGconn* handle () diff --git a/odb/pgsql/database.hxx b/odb/pgsql/database.hxx index 1b688fc..52e48c3 100644 --- a/odb/pgsql/database.hxx +++ b/odb/pgsql/database.hxx @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -98,6 +99,25 @@ namespace odb virtual odb::connection* connection_ (); + // SQL statement tracing. + // + public: + typedef pgsql::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: const std::string& user () const diff --git a/odb/pgsql/forward.hxx b/odb/pgsql/forward.hxx index 640d379..dd6f5ad 100644 --- a/odb/pgsql/forward.hxx +++ b/odb/pgsql/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/pgsql/makefile b/odb/pgsql/makefile index e447f8e..410650a 100644 --- a/odb/pgsql/makefile +++ b/odb/pgsql/makefile @@ -16,6 +16,7 @@ exceptions.cxx \ object-statements.cxx \ statement.cxx \ statements-base.cxx \ +tracer.cxx \ traits.cxx \ transaction.cxx \ transaction-impl.cxx \ diff --git a/odb/pgsql/statement.cxx b/odb/pgsql/statement.cxx index 049a00d..8a20456 100644 --- a/odb/pgsql/statement.cxx +++ b/odb/pgsql/statement.cxx @@ -9,6 +9,8 @@ #include +#include + #include #include #include @@ -68,6 +70,14 @@ namespace odb if (deallocated_) return; + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->deallocate (conn_, *this); + } + string s ("deallocate \""); s += name_; s += "\""; @@ -79,17 +89,26 @@ namespace odb statement:: statement (connection& conn, const string& name, - const string& stmt, + const string& text, const Oid* types, size_t types_count) : conn_ (conn), name_ (name), + text_ (text), deallocated_ (false) { + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->prepare (conn_, *this); + } + auto_handle h ( PQprepare (conn_.handle (), name_.c_str (), - stmt.c_str (), + text_.c_str (), static_cast (types_count), types)); @@ -102,6 +121,12 @@ namespace odb // } + const char* statement:: + text () const + { + return text_.c_str (); + } + void statement:: bind_param (native_binding& n, const binding& b) { @@ -384,6 +409,14 @@ namespace odb if (param_ != 0) bind_param (*native_param_, *param_); + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + bool in (native_param_ != 0); handle_.reset ( @@ -478,6 +511,14 @@ namespace odb { bind_param (native_param_, param_); + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + auto_handle h ( PQexecPrepared (conn_.handle (), name_.c_str (), @@ -570,6 +611,14 @@ namespace odb { bind_param (native_param_, param_); + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + auto_handle h ( PQexecPrepared (conn_.handle (), name_.c_str (), @@ -627,6 +676,14 @@ namespace odb if (param_ != 0) bind_param (native_param_, *param_); + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + auto_handle h ( PQexecPrepared (conn_.handle (), name_.c_str (), diff --git a/odb/pgsql/statement.hxx b/odb/pgsql/statement.hxx index 8beb01f..3230bb2 100644 --- a/odb/pgsql/statement.hxx +++ b/odb/pgsql/statement.hxx @@ -11,7 +11,8 @@ #include #include // std::size_t -#include +#include +#include #include #include @@ -26,12 +27,21 @@ namespace odb { class connection; - class LIBODB_PGSQL_EXPORT statement: public details::shared_base + class LIBODB_PGSQL_EXPORT statement: public odb::statement { public: virtual ~statement () = 0; + const char* + name () const + { + return name_.c_str (); + } + + virtual const char* + text () const; + void deallocate (); @@ -55,13 +65,14 @@ namespace odb protected: statement (connection&, const std::string& name, - const std::string& stmt, + const std::string& text, const Oid* types, std::size_t types_count); protected: connection& conn_; std::string name_; + std::string text_; private: bool deallocated_; diff --git a/odb/pgsql/tracer.cxx b/odb/pgsql/tracer.cxx new file mode 100644 index 0000000..b0cf4d2 --- /dev/null +++ b/odb/pgsql/tracer.cxx @@ -0,0 +1,62 @@ +// file : odb/pgsql/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 pgsql + { + 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/pgsql/tracer.hxx b/odb/pgsql/tracer.hxx new file mode 100644 index 0000000..9af7df8 --- /dev/null +++ b/odb/pgsql/tracer.hxx @@ -0,0 +1,62 @@ +// file : odb/pgsql/tracer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_PGSQL_TRACER_HXX +#define ODB_PGSQL_TRACER_HXX + +#include + +#include + +#include +#include + +namespace odb +{ + namespace pgsql + { + 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 pgsql::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_PGSQL_TRACER_HXX diff --git a/odb/pgsql/transaction-impl.cxx b/odb/pgsql/transaction-impl.cxx index e4604e3..ac90e93 100644 --- a/odb/pgsql/transaction-impl.cxx +++ b/odb/pgsql/transaction-impl.cxx @@ -7,6 +7,8 @@ #include +#include + #include #include #include @@ -46,6 +48,12 @@ namespace odb odb::transaction_impl::connection_ = connection_.get (); } + { + odb::tracer* t; + if ((t = connection_->tracer ()) || (t = database_.tracer ())) + t->execute (*connection_, "BEGIN"); + } + auto_handle h (PQexec (connection_->handle (), "begin")); if (!h || PGRES_COMMAND_OK != PQresultStatus (h)) @@ -55,6 +63,12 @@ namespace odb void transaction_impl:: commit () { + { + odb::tracer* t; + if ((t = connection_->tracer ()) || (t = database_.tracer ())) + t->execute (*connection_, "COMMIT"); + } + auto_handle h (PQexec (connection_->handle (), "commit")); if (!h || PGRES_COMMAND_OK != PQresultStatus (h)) @@ -64,6 +78,12 @@ namespace odb void transaction_impl:: rollback () { + { + odb::tracer* t; + if ((t = connection_->tracer ()) || (t = database_.tracer ())) + t->execute (*connection_, "ROLLBACK"); + } + auto_handle h (PQexec (connection_->handle (), "rollback")); if (!h || PGRES_COMMAND_OK != PQresultStatus (h)) diff --git a/odb/pgsql/transaction.hxx b/odb/pgsql/transaction.hxx index 39675d8..d56a08b 100644 --- a/odb/pgsql/transaction.hxx +++ b/odb/pgsql/transaction.hxx @@ -12,6 +12,7 @@ #include #include +#include #include @@ -51,6 +52,25 @@ namespace odb static void current (transaction&); + // SQL statement tracing. + // + public: + typedef pgsql::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