From 57d5d8fe9dc4c0d6b4ef21754c5a3539e4c01cf9 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/mysql/auto-handle.hxx | 2 +- odb/mysql/connection.cxx | 11 +++++ odb/mysql/connection.hxx | 20 +++++++++ odb/mysql/database.hxx | 20 +++++++++ odb/mysql/forward.hxx | 2 + odb/mysql/makefile | 1 + odb/mysql/statement.cxx | 96 ++++++++++++++++++++++++++++++------------ odb/mysql/statement.hxx | 16 +++++-- odb/mysql/tracer.cxx | 62 +++++++++++++++++++++++++++ odb/mysql/tracer.hxx | 62 +++++++++++++++++++++++++++ odb/mysql/transaction-impl.cxx | 20 +++++++++ odb/mysql/transaction.hxx | 20 +++++++++ 12 files changed, 300 insertions(+), 32 deletions(-) create mode 100644 odb/mysql/tracer.cxx create mode 100644 odb/mysql/tracer.hxx diff --git a/odb/mysql/auto-handle.hxx b/odb/mysql/auto-handle.hxx index 6950551..42e06e4 100644 --- a/odb/mysql/auto-handle.hxx +++ b/odb/mysql/auto-handle.hxx @@ -76,7 +76,7 @@ namespace odb return h; } - operator H* () + operator H* () const { return h_; } diff --git a/odb/mysql/connection.cxx b/odb/mysql/connection.cxx index 114ea38..473079d 100644 --- a/odb/mysql/connection.cxx +++ b/odb/mysql/connection.cxx @@ -97,6 +97,17 @@ namespace odb { clear (); + { + odb::tracer* t; + if ((t = transaction_tracer ()) || + (t = tracer ()) || + (t = database ().tracer ())) + { + string str (s, n); + t->execute (*this, str.c_str ()); + } + } + if (mysql_real_query (handle_, s, static_cast (n))) translate_error (*this); diff --git a/odb/mysql/connection.hxx b/odb/mysql/connection.hxx index a54194e..81e5019 100644 --- a/odb/mysql/connection.hxx +++ b/odb/mysql/connection.hxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,25 @@ namespace odb virtual unsigned long long execute (const char* statement, std::size_t length); + // SQL statement tracing. + // + public: + typedef mysql::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: bool failed () const diff --git a/odb/mysql/database.hxx b/odb/mysql/database.hxx index be9bb58..a245a37 100644 --- a/odb/mysql/database.hxx +++ b/odb/mysql/database.hxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -176,6 +177,25 @@ namespace odb connection_ptr connection (); + // SQL statement tracing. + // + public: + typedef mysql::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/mysql/forward.hxx b/odb/mysql/forward.hxx index 8ed934c..2252098 100644 --- a/odb/mysql/forward.hxx +++ b/odb/mysql/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/mysql/makefile b/odb/mysql/makefile index 2e6d5ad..069df5f 100644 --- a/odb/mysql/makefile +++ b/odb/mysql/makefile @@ -17,6 +17,7 @@ query.cxx \ query-const-expr.cxx \ statement.cxx \ statements-base.cxx \ +tracer.cxx \ transaction.cxx \ transaction-impl.cxx \ traits.cxx diff --git a/odb/mysql/statement.cxx b/odb/mysql/statement.cxx index d4e4943..04f59f6 100644 --- a/odb/mysql/statement.cxx +++ b/odb/mysql/statement.cxx @@ -5,9 +5,12 @@ #include +#include + #include -#include +#include #include +#include #include using namespace std; @@ -20,15 +23,34 @@ namespace odb // statement:: - statement (connection& conn) - : conn_ (conn), stmt_ (conn_.alloc_stmt_handle ()) + statement (connection& conn, const string& text) + : conn_ (conn), text_ (text), stmt_ (conn_.alloc_stmt_handle ()) { + conn_.clear (); + + if (mysql_stmt_prepare (stmt_, text_.c_str (), text_.size ()) != 0) + translate_error (conn_, stmt_); + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->prepare (conn_, *this); + } } statement:: ~statement () { + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->deallocate (conn_, *this); + } + // Let the connection handle the release of the statement (it // may delay the actual freeing if it will mess up the currently // active statement). @@ -36,6 +58,12 @@ namespace odb conn_.free_stmt_handle (stmt_); } + const char* statement:: + text () const + { + return text_.c_str (); + } + void statement:: cancel () { @@ -64,7 +92,7 @@ namespace odb const string& s, binding& param, binding& result) - : statement (conn), + : statement (conn, s), end_ (false), cached_ (false), rows_ (0), @@ -73,15 +101,11 @@ namespace odb result_ (result), result_version_ (0) { - conn_.clear (); - - if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - translate_error (conn_, stmt_); } select_statement:: select_statement (connection& conn, const string& s, binding& result) - : statement (conn), + : statement (conn, s), end_ (false), cached_ (false), rows_ (0), @@ -89,10 +113,6 @@ namespace odb result_ (result), result_version_ (0) { - conn_.clear (); - - if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - translate_error (conn_, stmt_); } void select_statement:: @@ -117,6 +137,14 @@ namespace odb param_version_ = param_->version; } + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + if (mysql_stmt_execute (stmt_)) translate_error (conn_, stmt_); @@ -249,12 +277,8 @@ namespace odb insert_statement:: insert_statement (connection& conn, const string& s, binding& param) - : statement (conn), param_ (param), param_version_ (0) + : statement (conn, s), param_ (param), param_version_ (0) { - conn_.clear (); - - if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - translate_error (conn_, stmt_); } bool insert_statement:: @@ -273,6 +297,14 @@ namespace odb param_version_ = param_.version; } + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + if (mysql_stmt_execute (stmt_)) { if (mysql_stmt_errno (stmt_) == ER_DUP_ENTRY) @@ -300,12 +332,8 @@ namespace odb update_statement:: update_statement (connection& conn, const string& s, binding& param) - : statement (conn), param_ (param), param_version_ (0) + : statement (conn, s), param_ (param), param_version_ (0) { - conn_.clear (); - - if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - translate_error (conn_, stmt_); } unsigned long long update_statement:: @@ -324,6 +352,14 @@ namespace odb param_version_ = param_.version; } + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + if (mysql_stmt_execute (stmt_)) translate_error (conn_, stmt_); @@ -345,12 +381,8 @@ namespace odb delete_statement:: delete_statement (connection& conn, const string& s, binding& param) - : statement (conn), param_ (param), param_version_ (0) + : statement (conn, s), param_ (param), param_version_ (0) { - conn_.clear (); - - if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - translate_error (conn_, stmt_); } unsigned long long delete_statement:: @@ -369,6 +401,14 @@ namespace odb param_version_ = param_.version; } + { + odb::tracer* t; + if ((t = conn_.transaction_tracer ()) || + (t = conn_.tracer ()) || + (t = conn_.database ().tracer ())) + t->execute (conn_, *this); + } + if (mysql_stmt_execute (stmt_)) translate_error (conn_, stmt_); diff --git a/odb/mysql/statement.hxx b/odb/mysql/statement.hxx index 93adea4..ee1284b 100644 --- a/odb/mysql/statement.hxx +++ b/odb/mysql/statement.hxx @@ -12,7 +12,7 @@ #include // std::size_t #include -#include +#include #include #include @@ -27,12 +27,21 @@ namespace odb { class connection; - class LIBODB_MYSQL_EXPORT statement: public details::shared_base + class LIBODB_MYSQL_EXPORT statement: public odb::statement { public: virtual ~statement () = 0; + MYSQL_STMT* + handle () const + { + return stmt_; + } + + virtual const char* + text () const; + // Cancel the statement execution (e.g., result fetching) so // that another statement can be executed on the connection. // @@ -40,10 +49,11 @@ namespace odb cancel (); protected: - statement (connection&); + statement (connection&, const std::string& text); protected: connection& conn_; + const std::string text_; auto_handle stmt_; }; diff --git a/odb/mysql/tracer.cxx b/odb/mysql/tracer.cxx new file mode 100644 index 0000000..7b5a03d --- /dev/null +++ b/odb/mysql/tracer.cxx @@ -0,0 +1,62 @@ +// file : odb/mysql/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 mysql + { + 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/mysql/tracer.hxx b/odb/mysql/tracer.hxx new file mode 100644 index 0000000..87116d5 --- /dev/null +++ b/odb/mysql/tracer.hxx @@ -0,0 +1,62 @@ +// file : odb/mysql/tracer.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_MYSQL_TRACER_HXX +#define ODB_MYSQL_TRACER_HXX + +#include + +#include + +#include +#include + +namespace odb +{ + namespace mysql + { + 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 mysql::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_MYSQL_TRACER_HXX diff --git a/odb/mysql/transaction-impl.cxx b/odb/mysql/transaction-impl.cxx index 24c511f..7aa86a5 100644 --- a/odb/mysql/transaction-impl.cxx +++ b/odb/mysql/transaction-impl.cxx @@ -3,6 +3,8 @@ // copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file +#include + #include #include #include @@ -41,6 +43,12 @@ namespace odb odb::transaction_impl::connection_ = connection_.get (); } + { + odb::tracer* t; + if ((t = connection_->tracer ()) || (t = database_.tracer ())) + t->execute (*connection_, "BEGIN"); + } + if (mysql_real_query (connection_->handle (), "begin", 5) != 0) translate_error (*connection_); } @@ -50,6 +58,12 @@ namespace odb { connection_->clear (); + { + odb::tracer* t; + if ((t = connection_->tracer ()) || (t = database_.tracer ())) + t->execute (*connection_, "COMMIT"); + } + if (mysql_real_query (connection_->handle (), "commit", 6) != 0) translate_error (*connection_); @@ -63,6 +77,12 @@ namespace odb { connection_->clear (); + { + odb::tracer* t; + if ((t = connection_->tracer ()) || (t = database_.tracer ())) + t->execute (*connection_, "ROLLBACK"); + } + if (mysql_real_query (connection_->handle (), "rollback", 8) != 0) translate_error (*connection_); diff --git a/odb/mysql/transaction.hxx b/odb/mysql/transaction.hxx index 90182e1..7ef1e17 100644 --- a/odb/mysql/transaction.hxx +++ b/odb/mysql/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 mysql::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