From 10a83d0453f65c41c3915c906f2d6cf9d6ff349e Mon Sep 17 00:00:00 2001 From: Constantin Michael Date: Fri, 13 May 2011 15:56:57 +0200 Subject: Add PGresult pointer wrapper --- odb/pgsql/database.cxx | 24 +++++++------ odb/pgsql/error.cxx | 78 ++++++++++++------------------------------ odb/pgsql/error.hxx | 25 ++++++-------- odb/pgsql/error.ixx | 29 ++++++++++++++++ odb/pgsql/result-ptr.hxx | 49 ++++++++++++++++++++++++++ odb/pgsql/transaction-impl.cxx | 49 +++++++------------------- 6 files changed, 137 insertions(+), 117 deletions(-) create mode 100644 odb/pgsql/error.ixx create mode 100644 odb/pgsql/result-ptr.hxx (limited to 'odb') diff --git a/odb/pgsql/database.cxx b/odb/pgsql/database.cxx index ac7a991..721e600 100644 --- a/odb/pgsql/database.cxx +++ b/odb/pgsql/database.cxx @@ -4,12 +4,14 @@ // license : GNU GPL v2; see accompanying LICENSE file #include +#include // std::atol #include #include #include #include #include +#include #include @@ -217,21 +219,23 @@ namespace odb connection_type& c (transaction::current ().connection ()); - PGresult* r = PQexec (c.handle (), s); + result_ptr r (PQexec (c.handle (), s)); + PGresult* h (r.get ()); - ExecStatusType status; unsigned long long count (0); - if (!r) - translate_result_error (c); - else if (!is_good_result (r, &status)) - translate_result_error (c, r, status); - else if (status == PGRES_TUPLES_OK) - count = static_cast (PQntuples (r)); + if (!is_good_result (h)) + translate_error (c, h); + else if (PGRES_TUPLES_OK == PQresultStatus (h)) + count = static_cast (PQntuples (h)); else { - istringstream ss (PQcmdTuples (r)); - ss >> count; + const char* s (PQcmdTuples (h)); + + if (s[0] != '\0' && s[1] == '\0') + count = static_cast (s[0] - '0'); + else + count = static_cast (atol (s)); } return count; diff --git a/odb/pgsql/error.cxx b/odb/pgsql/error.cxx index f65cbee..cb11872 100644 --- a/odb/pgsql/error.cxx +++ b/odb/pgsql/error.cxx @@ -17,7 +17,7 @@ namespace odb namespace pgsql { void - translate_connection_error (connection& c) + translate_error (connection& c) { PGconn* h (c.handle ()); @@ -30,14 +30,20 @@ namespace odb } void - translate_result_error_ (connection& c, - ExecStatusType status = PGRES_EMPTY_QUERY, - const char* sqlstate = 0, - const char* error_message = 0) + translate_error (connection& c, + PGresult* r) { - PGconn* h (c.handle ()); + if (!r) + { + if (CONNECTION_BAD == PQstatus (c.handle ())) + throw connection_lost (); + else + throw bad_alloc (); + } - switch (status) + const char* error_message (PQresultErrorMessage (r)); + + switch (PQresultStatus (r)) { case PGRES_BAD_RESPONSE: { @@ -49,67 +55,25 @@ namespace odb case PGRES_FATAL_ERROR: { - assert (sqlstate); + const char* ss (PQresultErrorField (r, PG_DIAG_SQLSTATE)); + + assert (ss); assert (error_message); // Deadlock detected. // - if (std::string ("40P01") == sqlstate) + if (std::string ("40P01") == ss) throw deadlock (); - else if (CONNECTION_BAD == PQstatus (h)) + else if (CONNECTION_BAD == PQstatus (c.handle ())) throw connection_lost (); else - throw database_exception (sqlstate, error_message); + throw database_exception (ss, error_message); } - default: - { - if (CONNECTION_BAD == PQstatus (h)) - throw connection_lost (); - else - throw bad_alloc (); - } - }; - } - - bool - is_good_result (PGresult* r, ExecStatusType* s) - { - if (r != 0) - { - ExecStatusType status (PQresultStatus (r)); - - if (s != 0) - *s = status; - - return - *s != PGRES_BAD_RESPONSE && - *s != PGRES_NONFATAL_ERROR && - *s != PGRES_FATAL_ERROR; - } - - return false; - } - - void - translate_result_error (connection& c, - PGresult* r, - ExecStatusType s, - bool clear_result) - { - if (!r) - translate_result_error_ (c); - else - { - const char* ss (PQresultErrorField (r, PG_DIAG_SQLSTATE)); - const char* m (PQresultErrorMessage (r)); - - if (clear_result) - PQclear (r); - - translate_result_error_ (c, s, ss, m); + assert (0); + break; } } } diff --git a/odb/pgsql/error.hxx b/odb/pgsql/error.hxx index d4ea9e1..139a33c 100644 --- a/odb/pgsql/error.hxx +++ b/odb/pgsql/error.hxx @@ -21,7 +21,15 @@ namespace odb class connection; LIBODB_PGSQL_EXPORT void - translate_connection_error (connection&); + translate_error (connection&); + + // Translate an error condition involving a PGresult*. If r is null, it is + // assumed that the error was caused due to a bad connection or a memory + // allocation error. + // + LIBODB_PGSQL_EXPORT void + translate_error (connection& c, + PGresult* r); // Return true if the PGresult is in an error state. If both s and r are // non-null, the pointed to value will be populated with the result status. @@ -29,22 +37,11 @@ namespace odb // LIBODB_PGSQL_EXPORT bool is_good_result (PGresult* r, ExecStatusType* s = 0); - - // Translate an error condition involving a PGresult*. If r is null, it is - // assumed that the error was caused due to a bad connection or a memory - // allocation error. All remaining parameters except c are ignored. If r - // is non-null, the error is translated using the provided result status, - // s. Error descriptions are obtained using r. If clear_result is true, - // the resources associated with r are released via PQclear(). - // - LIBODB_PGSQL_EXPORT void - translate_result_error (connection& c, - PGresult* r = 0, - ExecStatusType s = PGRES_EMPTY_QUERY, - bool clear_result = true); } } +#include + #include #endif // ODB_PGSQL_ERRORS_HXX diff --git a/odb/pgsql/error.ixx b/odb/pgsql/error.ixx new file mode 100644 index 0000000..5bbc698 --- /dev/null +++ b/odb/pgsql/error.ixx @@ -0,0 +1,29 @@ +// file : odb/pgsql/error.ixx +// author : Constantin Michael +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace pgsql + { + bool + inline is_good_result (PGresult* r, ExecStatusType* s) + { + if (r != 0) + { + ExecStatusType status (PQresultStatus (r)); + + if (s != 0) + *s = status; + + return + status != PGRES_BAD_RESPONSE && + status != PGRES_NONFATAL_ERROR && + status != PGRES_FATAL_ERROR; + } + + return false; + } + } +} diff --git a/odb/pgsql/result-ptr.hxx b/odb/pgsql/result-ptr.hxx new file mode 100644 index 0000000..1772cc9 --- /dev/null +++ b/odb/pgsql/result-ptr.hxx @@ -0,0 +1,49 @@ +// file : odb/pgsql/result-ptr.hxx +// author : Constantin Michael +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_PGSQL_RESULT_PTR_HXX +#define ODB_PGSQL_RESULT_PTR_HXX + +#include + +#include + +#include + +#include + +namespace odb +{ + namespace pgsql + { + class LIBODB_PGSQL_EXPORT result_ptr + { + public: + result_ptr (PGresult* r) + : r_ (r) + { + } + + ~result_ptr () + { + if (r_) + PQclear (r_); + } + + PGresult* + get () + { + return r_; + } + + private: + PGresult* r_; + }; + } +} + +#include + +#endif // ODB_PGSQL_RESULT_PTR_HXX diff --git a/odb/pgsql/transaction-impl.cxx b/odb/pgsql/transaction-impl.cxx index 2d2a988..eb93361 100644 --- a/odb/pgsql/transaction-impl.cxx +++ b/odb/pgsql/transaction-impl.cxx @@ -12,6 +12,7 @@ #include #include #include +#include namespace odb { @@ -21,15 +22,11 @@ namespace odb transaction_impl (database_type& db) : odb::transaction_impl (db), connection_ (db.connection ()) { - PGresult* r (PQexec (connection_->handle (), "begin")); + result_ptr r (PQexec (connection_->handle (), "begin")); + PGresult* h (r.get ()); - if (!r) - translate_result_error (*connection_); - - ExecStatusType s (PQresultStatus (r)); - - if (PGRES_COMMAND_OK != s) - translate_result_error (*connection_, r, s); + if (!h || PGRES_COMMAND_OK != PQresultStatus (h)) + translate_error (*connection_, h); } transaction_impl:: @@ -40,41 +37,21 @@ namespace odb void transaction_impl:: commit () { - // connection_->clear (); - - PGresult* r (PQexec (connection_->handle (), "commit")); - - if (!r) - translate_result_error (*connection_); - - ExecStatusType s (PQresultStatus (r)); + result_ptr r (PQexec (connection_->handle (), "commit")); + PGresult* h (r.get ()); - if (PGRES_COMMAND_OK != s) - translate_result_error (*connection_, r, s); - - // Release the connection. - // - // connection_.reset (); + if (!h || PGRES_COMMAND_OK != PQresultStatus (h)) + translate_error (*connection_, h); } void transaction_impl:: rollback () { - // connection_->clear (); - - PGresult* r (PQexec (connection_->handle (), "rollback")); - - if (!r) - translate_result_error (*connection_); - - ExecStatusType s (PQresultStatus (r)); - - if (PGRES_COMMAND_OK != s) - translate_result_error (*connection_, r, s); + result_ptr r (PQexec (connection_->handle (), "rollback")); + PGresult* h (r.get ()); - // Release the connection. - // - //connection_.reset (); + if (!h || PGRES_COMMAND_OK != PQresultStatus (h)) + translate_error (*connection_, h); } } } -- cgit v1.1