diff options
-rw-r--r-- | odb/pgsql/statement.cxx | 179 | ||||
-rw-r--r-- | odb/pgsql/statement.hxx | 110 |
2 files changed, 289 insertions, 0 deletions
diff --git a/odb/pgsql/statement.cxx b/odb/pgsql/statement.cxx new file mode 100644 index 0000000..efd7f8e --- /dev/null +++ b/odb/pgsql/statement.cxx @@ -0,0 +1,179 @@ +// file : odb/pgsql/statement.cxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cstdlib> // std::atol +#include <cassert> + +#include <odb/pgsql/statement.hxx> +#include <odb/pgsql/connection.hxx> +#include <odb/pgsql/transaction.hxx> +#include <odb/pgsql/result-ptr.hxx> +#include <odb/pgsql/error.hxx> + +using namespace std; + +namespace odb +{ + namespace pgsql + { + // + // statement + // + + statement:: + ~statement () + { + try + { + release (); + } + catch (...) + { + } + } + + statement:: + statement (connection& conn, + const string& name, + const string& stmt, + const Oid* types, + size_t n) + : conn_ (conn), + name_ (name) + { + result_ptr r (PQprepare (conn_.handle (), + name_.c_str (), + stmt.c_str (), + n, + types)); + + if (!is_good_result (r.get ())) + translate_error (conn_, r.get ()); + } + + void statement:: + release () + { + if (!name_.empty ()) + { + string s ("deallocate "); + s += name_; + + transaction t (conn_.database ().begin ()); + conn_.database ().execute (s.c_str ()); + t.commit (); + } + } + + // + // insert_statement + // + + insert_statement:: + ~insert_statement () + { + } + + insert_statement:: + insert_statement (connection& conn, + const string& name, + const string& stmt, + const Oid* types, + size_t n, + native_binding& data) + : statement (conn, name, stmt, types, n), + data_ (data) + { + } + + bool insert_statement:: + execute () + { + result_ptr r (PQexecPrepared (conn_.handle (), + name_.c_str (), + data_.count, + data_.values, + data_.lengths, + data_.formats, + 1)); + PGresult* h (r.get ()); + ExecStatusType stat; + + if (!is_good_result (h, &stat)) + { + if (PGRES_FATAL_ERROR == stat) + { + string s (PQresultErrorField (h, PG_DIAG_SQLSTATE)); + + if (s == "23505") + return false; + } + + translate_error (conn_, h); + } + + oid_ = PQoidValue (h); + + return true; + } + + unsigned long long insert_statement:: + id () + { + // @@ Need to check what InvalidOid evaluates to. + // Is this function signature required? + // + return static_cast<unsigned long long> (oid_); + } + + + // + // delete_statement + // + + delete_statement:: + ~delete_statement () + { + } + + delete_statement:: + delete_statement (connection& conn, + const string& name, + const string& stmt, + const Oid* types, + size_t n, + native_binding& cond) + : statement (conn, name, stmt, types, n), + cond_ (cond) + { + } + + unsigned long long delete_statement:: + execute () + { + result_ptr r (PQexecPrepared (conn_.handle (), + name_.c_str (), + cond_.count, + cond_.values, + cond_.lengths, + cond_.formats, + 1)); + PGresult* h (r.get ()); + + if (!is_good_result (h)) + translate_error (conn_, h); + + const char* s = PQcmdTuples (h); + unsigned long long count; + + 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; + } + } +} diff --git a/odb/pgsql/statement.hxx b/odb/pgsql/statement.hxx new file mode 100644 index 0000000..88b1c14 --- /dev/null +++ b/odb/pgsql/statement.hxx @@ -0,0 +1,110 @@ +// file : odb/pgsql/statement.hxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_PGSQL_STATEMENT_HXX +#define ODB_PGSQL_STATEMENT_HXX + +#include <odb/pre.hxx> + +#include <string> +#include <cstddef> // std::size_t + +#include <libpq-fe.h> + +#include <odb/details/shared-ptr.hxx> + +#include <odb/pgsql/version.hxx> +#include <odb/pgsql/binding.hxx> + +#include <odb/pgsql/details/export.hxx> + +namespace odb +{ + namespace pgsql + { + class connection; + + class LIBODB_PGSQL_EXPORT statement: public details::shared_base + { + public: + virtual + ~statement () = 0; + + protected: + statement (connection&, + const std::string& name, + const std::string& stmt, + const Oid* types, + std::size_t n); + + protected: + connection& conn_; + std::string name_; + + private: + void + release (); + }; + + class LIBODB_PGSQL_EXPORT insert_statement: public statement + { + public: + virtual + ~insert_statement (); + + insert_statement (connection& conn, + const std::string& name, + const std::string& stmt, + const Oid* types, + std::size_t n, + native_binding& data); + + // Return true if successful and false if the row is a duplicate. + // All other errors are reported by throwing exceptions. + // + bool + execute (); + + unsigned long long + id (); + + private: + insert_statement (const insert_statement&); + insert_statement& operator= (const insert_statement&); + + private: + native_binding& data_; + Oid oid_; + }; + + class LIBODB_PGSQL_EXPORT delete_statement: public statement + { + public: + virtual + ~delete_statement (); + + delete_statement (connection& conn, + const std::string& name, + const std::string& stmt, + const Oid* types, + std::size_t n, + native_binding& cond); + + unsigned long long + execute (); + + private: + delete_statement (const delete_statement&); + delete_statement& operator= (const delete_statement&); + + private: + native_binding& cond_; + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_PGSQL_STATEMENT_HXX |