From 4acabe57939ff37bad0a8aabc5164b6d5add449b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 18 Feb 2011 17:56:53 +0200 Subject: Factor out MySQL error to exception translation into separate function --- odb/mysql/connection.cxx | 14 ++++++- odb/mysql/database.cxx | 12 ++---- odb/mysql/error.cxx | 60 ++++++++++++++++++++++++++++ odb/mysql/error.hxx | 36 +++++++++++++++++ odb/mysql/exceptions.cxx | 37 ------------------ odb/mysql/exceptions.hxx | 7 ---- odb/mysql/makefile | 1 + odb/mysql/statement.cxx | 88 ++++++++++++++---------------------------- odb/mysql/transaction-impl.cxx | 20 ++++------ 9 files changed, 148 insertions(+), 127 deletions(-) create mode 100644 odb/mysql/error.cxx create mode 100644 odb/mysql/error.hxx diff --git a/odb/mysql/connection.cxx b/odb/mysql/connection.cxx index e77c04d..1395592 100644 --- a/odb/mysql/connection.cxx +++ b/odb/mysql/connection.cxx @@ -4,6 +4,7 @@ // license : GNU GPL v2; see accompanying LICENSE file #include // std::bad_alloc +#include #include #include @@ -40,9 +41,18 @@ namespace odb db.socket (), db.client_flags () | CLIENT_FOUND_ROWS) == 0) { - database_exception e (handle_); + // We cannot use translate_error() here since there is no connection + // yet. + // + unsigned int e (mysql_errno (handle_)); + string sqlstate (mysql_sqlstate (handle_)); + string message (mysql_error (handle_)); mysql_close (handle_); - throw e; + + if (e == CR_OUT_OF_MEMORY) + throw bad_alloc (); + + throw database_exception (e, sqlstate, message); } } diff --git a/odb/mysql/database.cxx b/odb/mysql/database.cxx index da19ab5..72b18d8 100644 --- a/odb/mysql/database.cxx +++ b/odb/mysql/database.cxx @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -220,14 +221,7 @@ namespace odb MYSQL* h (c.handle ()); if (mysql_real_query (h, s, static_cast (n))) - { - unsigned int e (mysql_errno (h)); - - if (e == ER_LOCK_DEADLOCK) - throw deadlock (); - else - throw database_exception (h); - } + translate_error (c); // Get the affected row count, if any. If the statement has a result // set (e.g., SELECT), we first need to call mysql_store_result(). @@ -244,7 +238,7 @@ namespace odb mysql_free_result (rs); } else - throw database_exception (h); + translate_error (c); } return r; diff --git a/odb/mysql/error.cxx b/odb/mysql/error.cxx new file mode 100644 index 0000000..460816a --- /dev/null +++ b/odb/mysql/error.cxx @@ -0,0 +1,60 @@ +// file : odb/mysql/errors.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::bad_alloc + +#include +#include +#include + +using namespace std; + +namespace odb +{ + namespace mysql + { + void + translate_error (connection&, + unsigned int e, + const std::string& sqlstate, + const std::string& message) + { + switch (e) + { + case CR_OUT_OF_MEMORY: + { + throw bad_alloc (); + } + case ER_LOCK_DEADLOCK: + { + throw deadlock (); + } + default: + { + throw database_exception (e, sqlstate, message); + } + } + } + + void + translate_error (connection& c) + { + MYSQL* h (c.handle ()); + translate_error (c, + mysql_errno (h), + mysql_sqlstate (h), + mysql_error (h)); + } + + void + translate_error (connection& c, MYSQL_STMT* h) + { + translate_error (c, + mysql_stmt_errno (h), + mysql_stmt_sqlstate (h), + mysql_stmt_error (h)); + } + } +} diff --git a/odb/mysql/error.hxx b/odb/mysql/error.hxx new file mode 100644 index 0000000..6aeec0d --- /dev/null +++ b/odb/mysql/error.hxx @@ -0,0 +1,36 @@ +// file : odb/mysql/errors.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_MYSQL_ERRORS_HXX +#define ODB_MYSQL_ERRORS_HXX + +#include + +#include +#include + +#include + +namespace odb +{ + namespace mysql + { + class connection; + + // Translate MySQL error and throw an appropriate exception. Also, + // if the error code indicates that the connection is no longer + // usable, mark it as failed. + // + LIBODB_MYSQL_EXPORT void + translate_error (connection&); + + LIBODB_MYSQL_EXPORT void + translate_error (connection&, MYSQL_STMT*); + } +} + +#include + +#endif // ODB_MYSQL_ERRORS_HXX diff --git a/odb/mysql/exceptions.cxx b/odb/mysql/exceptions.cxx index d87b6c2..dd9e199 100644 --- a/odb/mysql/exceptions.cxx +++ b/odb/mysql/exceptions.cxx @@ -3,10 +3,8 @@ // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file -#include // std::bad_alloc #include -#include #include using namespace std; @@ -25,47 +23,12 @@ namespace odb } database_exception:: - database_exception (MYSQL* h) - : error_ (mysql_errno (h)) - { - if (error_ == CR_OUT_OF_MEMORY) - throw bad_alloc (); - - sqlstate_ = mysql_sqlstate (h); - message_ = mysql_error (h); - - init (); - } - - database_exception:: - database_exception (MYSQL_STMT* h) - : error_ (mysql_stmt_errno (h)) - { - if (error_ == CR_OUT_OF_MEMORY) - throw bad_alloc (); - - sqlstate_ = mysql_stmt_sqlstate (h); - message_ = mysql_stmt_error (h); - - init (); - } - - database_exception:: database_exception (unsigned int e, const string& s, const string& m) : error_ (e) { - if (error_ == CR_OUT_OF_MEMORY) - throw bad_alloc (); - sqlstate_ = s; message_ = m; - init (); - } - - void database_exception:: - init () - { ostringstream ostr; ostr << error_ << " (" << sqlstate_ << "): " << message_; what_ = ostr.str (); diff --git a/odb/mysql/exceptions.hxx b/odb/mysql/exceptions.hxx index 12af4c4..f0c17e4 100644 --- a/odb/mysql/exceptions.hxx +++ b/odb/mysql/exceptions.hxx @@ -12,7 +12,6 @@ #include -#include #include #include @@ -23,8 +22,6 @@ namespace odb { struct LIBODB_MYSQL_EXPORT database_exception: odb::database_exception { - database_exception (MYSQL*); - database_exception (MYSQL_STMT*); database_exception (unsigned int, const std::string& sqlstate, const std::string& message); @@ -53,10 +50,6 @@ namespace odb what () const throw (); private: - void - init (); - - private: unsigned int error_; std::string sqlstate_; std::string message_; diff --git a/odb/mysql/makefile b/odb/mysql/makefile index d56f67a..024b14f 100644 --- a/odb/mysql/makefile +++ b/odb/mysql/makefile @@ -9,6 +9,7 @@ cxx := \ connection.cxx \ connection-factory.cxx \ database.cxx \ +error.cxx \ exceptions.cxx \ object-statements.cxx \ transaction.cxx \ diff --git a/odb/mysql/statement.cxx b/odb/mysql/statement.cxx index 8dbdc30..e1516f2 100644 --- a/odb/mysql/statement.cxx +++ b/odb/mysql/statement.cxx @@ -6,6 +6,7 @@ #include #include #include +#include #include using namespace std; @@ -71,7 +72,7 @@ namespace odb a->cancel (); if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - throw database_exception (stmt_); + translate_error (conn_, stmt_); } void select_statement:: @@ -87,12 +88,12 @@ namespace odb rows_ = 0; if (mysql_stmt_reset (stmt_)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); if (cond_version_ != cond_.version) { if (mysql_stmt_bind_param (stmt_, cond_.bind)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); cond_version_ = cond_.version; } @@ -100,20 +101,13 @@ namespace odb if (data_version_ != data_.version) { if (mysql_stmt_bind_result (stmt_, data_.bind)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); data_version_ = data_.version; } if (mysql_stmt_execute (stmt_)) - { - unsigned int e (mysql_stmt_errno (stmt_)); - - if (e == ER_LOCK_DEADLOCK) - throw deadlock (); - else - throw database_exception (stmt_); - } + translate_error (conn_, stmt_); conn_.active (this); } @@ -126,7 +120,7 @@ namespace odb if (!end_) { if (mysql_stmt_store_result (stmt_)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); // mysql_stmt_num_rows() returns the number of rows that have been // fetched by store_result. @@ -149,7 +143,7 @@ namespace odb if (cached_ && data_version_ != data_.version) { if (mysql_stmt_bind_result (stmt_, data_.bind)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); data_version_ = data_.version; } @@ -175,7 +169,8 @@ namespace odb } default: { - throw database_exception (stmt_); + translate_error (conn_, stmt_); + return no_data; // Never reaches. } } } @@ -193,7 +188,7 @@ namespace odb if (mysql_stmt_fetch_column ( stmt_, data_.bind + i, static_cast (i), 0)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); } } } @@ -206,7 +201,7 @@ namespace odb rows_ = 0; if (mysql_stmt_free_result (stmt_)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); if (conn_.active () == this) conn_.active (0); @@ -239,7 +234,7 @@ namespace odb a->cancel (); if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - throw database_exception (stmt_); + translate_error (conn_, stmt_); } bool insert_statement:: @@ -249,33 +244,22 @@ namespace odb a->cancel (); if (mysql_stmt_reset (stmt_)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); if (data_version_ != data_.version) { if (mysql_stmt_bind_param (stmt_, data_.bind)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); data_version_ = data_.version; } if (mysql_stmt_execute (stmt_)) { - switch (mysql_stmt_errno (stmt_)) - { - case ER_DUP_ENTRY: - { - return false; - } - case ER_LOCK_DEADLOCK: - { - throw deadlock (); - } - default: - { - throw database_exception (stmt_); - } - } + if (mysql_stmt_errno (stmt_) == ER_DUP_ENTRY) + return false; + else + translate_error (conn_, stmt_); } return true; @@ -304,7 +288,7 @@ namespace odb a->cancel (); if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - throw database_exception (stmt_); + translate_error (conn_, stmt_); } void update_statement:: @@ -314,7 +298,7 @@ namespace odb a->cancel (); if (mysql_stmt_reset (stmt_)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); if (image_version_ != image_.version || id_version_ != id_.version) { @@ -322,21 +306,14 @@ namespace odb // id parameter. // if (mysql_stmt_bind_param (stmt_, image_.bind)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); id_version_ = id_.version; image_version_ = image_.version; } if (mysql_stmt_execute (stmt_)) - { - unsigned int e (mysql_stmt_errno (stmt_)); - - if (e == ER_LOCK_DEADLOCK) - throw deadlock (); - else - throw database_exception (stmt_); - } + translate_error (conn_, stmt_); my_ulonglong r (mysql_stmt_affected_rows (stmt_)); @@ -346,7 +323,7 @@ namespace odb if (r == 0) throw object_not_persistent (); else - throw database_exception (stmt_); + translate_error (conn_, stmt_); } // delete_statement @@ -365,7 +342,7 @@ namespace odb a->cancel (); if (mysql_stmt_prepare (stmt_, s.c_str (), s.size ()) != 0) - throw database_exception (stmt_); + translate_error (conn_, stmt_); } unsigned long long delete_statement:: @@ -375,30 +352,23 @@ namespace odb a->cancel (); if (mysql_stmt_reset (stmt_)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); if (cond_version_ != cond_.version) { if (mysql_stmt_bind_param (stmt_, cond_.bind)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); cond_version_ = cond_.version; } if (mysql_stmt_execute (stmt_)) - { - unsigned int e (mysql_stmt_errno (stmt_)); - - if (e == ER_LOCK_DEADLOCK) - throw deadlock (); - else - throw database_exception (stmt_); - } + translate_error (conn_, stmt_); my_ulonglong r (mysql_stmt_affected_rows (stmt_)); if (r == static_cast (-1)) - throw database_exception (stmt_); + translate_error (conn_, stmt_); return static_cast (r); } diff --git a/odb/mysql/transaction-impl.cxx b/odb/mysql/transaction-impl.cxx index 73011b4..b523568 100644 --- a/odb/mysql/transaction-impl.cxx +++ b/odb/mysql/transaction-impl.cxx @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include namespace odb @@ -18,10 +18,8 @@ namespace odb transaction_impl (database_type& db) : odb::transaction_impl (db), connection_ (db.connection ()) { - MYSQL* h (connection_->handle ()); - - if (mysql_real_query (h, "begin", 5) != 0) - throw database_exception (h); + if (mysql_real_query (connection_->handle (), "begin", 5) != 0) + translate_error (*connection_); } transaction_impl:: @@ -35,10 +33,8 @@ namespace odb if (statement* a = connection_->active ()) a->cancel (); - MYSQL* h (connection_->handle ()); - - if (mysql_real_query (h, "commit", 6) != 0) - throw database_exception (h); + if (mysql_real_query (connection_->handle (), "commit", 6) != 0) + translate_error (*connection_); // Release the connection. // @@ -51,10 +47,8 @@ namespace odb if (statement* a = connection_->active ()) a->cancel (); - MYSQL* h (connection_->handle ()); - - if (mysql_real_query (h, "rollback", 8) != 0) - throw database_exception (h); + if (mysql_real_query (connection_->handle (), "rollback", 8) != 0) + translate_error (*connection_); // Release the connection. // -- cgit v1.1