diff options
Diffstat (limited to 'libodb-pgsql/odb/pgsql/connection.cxx')
-rw-r--r-- | libodb-pgsql/odb/pgsql/connection.cxx | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/libodb-pgsql/odb/pgsql/connection.cxx b/libodb-pgsql/odb/pgsql/connection.cxx new file mode 100644 index 0000000..80a1dd2 --- /dev/null +++ b/libodb-pgsql/odb/pgsql/connection.cxx @@ -0,0 +1,141 @@ +// file : odb/pgsql/connection.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include <new> // std::bad_alloc +#include <string> +#include <cstring> // std::strcmp +#include <cstdlib> // std::atol + +#include <libpq-fe.h> + +#include <odb/pgsql/database.hxx> +#include <odb/pgsql/connection.hxx> +#include <odb/pgsql/transaction.hxx> +#include <odb/pgsql/error.hxx> +#include <odb/pgsql/exceptions.hxx> +#include <odb/pgsql/statement-cache.hxx> + +using namespace std; + +extern "C" void +odb_pgsql_process_notice (void*, const char*) +{ +} + +namespace odb +{ + namespace pgsql + { + connection:: + connection (connection_factory& cf) + : odb::connection (cf), failed_ (false) + { + database_type& db (database ()); + handle_.reset (PQconnectdb (db.conninfo ().c_str ())); + + if (handle_ == 0) + throw bad_alloc (); + else if (PQstatus (handle_) == CONNECTION_BAD) + throw database_exception (PQerrorMessage (handle_)); + + init (); + } + + connection:: + connection (connection_factory& cf, PGconn* handle) + : odb::connection (cf), handle_ (handle), failed_ (false) + { + init (); + } + + void connection:: + init () + { + // Establish whether date/time values are represented as + // 8-byte integers. + // + if (strcmp (PQparameterStatus (handle_, "integer_datetimes"), "on") != 0) + throw database_exception ("unsupported binary format for PostgreSQL " + "date-time SQL types"); + + // Suppress server notifications to stdout. + // + PQsetNoticeProcessor (handle_, &odb_pgsql_process_notice, 0); + + // Create statement cache. + // + statement_cache_.reset (new statement_cache_type (*this)); + } + + connection:: + ~connection () + { + // Destroy prepared query statements before freeing the connections. + // + recycle (); + clear_prepared_map (); + } + + int connection:: + server_version () const + { + return PQserverVersion (handle_); + } + + transaction_impl* connection:: + begin () + { + return new transaction_impl (connection_ptr (inc_ref (this))); + } + + unsigned long long connection:: + execute (const char* s, std::size_t n) + { + // The string may not be '\0'-terminated. + // + string str (s, n); + + { + odb::tracer* t; + if ((t = transaction_tracer ()) || + (t = tracer ()) || + (t = database ().tracer ())) + t->execute (*this, str.c_str ()); + } + + auto_handle<PGresult> h (PQexec (handle_, str.c_str ())); + + unsigned long long count (0); + + if (!is_good_result (h)) + translate_error (*this, h); + else if (PGRES_TUPLES_OK == PQresultStatus (h)) + count = static_cast<unsigned long long> (PQntuples (h)); + else + { + const char* s (PQcmdTuples (h)); + + if (s[0] != '\0' && s[1] == '\0') + count = static_cast<unsigned long long> (s[0] - '0'); + else + count = static_cast<unsigned long long> (atol (s)); + } + + return count; + } + + // connection_factory + // + connection_factory:: + ~connection_factory () + { + } + + void connection_factory:: + database (database_type& db) + { + odb::connection_factory::db_ = &db; + db_ = &db; + } + } +} |