aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/pgsql/statement.cxx179
-rw-r--r--odb/pgsql/statement.hxx110
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