aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/mysql/connection.cxx2
-rw-r--r--odb/mysql/connection.hxx11
-rw-r--r--odb/mysql/makefile3
-rw-r--r--odb/mysql/statement.cxx42
-rw-r--r--odb/mysql/statement.hxx173
-rw-r--r--odb/mysql/statement.txx53
6 files changed, 282 insertions, 2 deletions
diff --git a/odb/mysql/connection.cxx b/odb/mysql/connection.cxx
index 9edb814..2e42b9e 100644
--- a/odb/mysql/connection.cxx
+++ b/odb/mysql/connection.cxx
@@ -15,7 +15,7 @@ namespace odb
{
connection::
connection (database& db)
- : handle_ (&mysql_)
+ : handle_ (&mysql_), statement_cache_ (*this)
{
if (mysql_init (handle_) == 0)
throw std::bad_alloc ();
diff --git a/odb/mysql/connection.hxx b/odb/mysql/connection.hxx
index e0f44a3..9718189 100644
--- a/odb/mysql/connection.hxx
+++ b/odb/mysql/connection.hxx
@@ -11,6 +11,8 @@
#include <odb/forward.hxx>
#include <odb/shared-ptr.hxx>
+#include <odb/mysql/statement.hxx>
+
namespace odb
{
namespace mysql
@@ -18,6 +20,8 @@ namespace odb
class connection: public shared_base
{
public:
+ typedef mysql::statement_cache statement_cache_type;
+
connection (database&);
virtual
@@ -30,6 +34,12 @@ namespace odb
return handle_;
}
+ statement_cache_type&
+ statement_cache ()
+ {
+ return statement_cache_;
+ }
+
private:
connection (const connection&);
connection& operator= (const connection&);
@@ -37,6 +47,7 @@ namespace odb
private:
MYSQL mysql_;
MYSQL* handle_;
+ statement_cache_type statement_cache_;
};
}
}
diff --git a/odb/mysql/makefile b/odb/mysql/makefile
index ce2204e..e577f98 100644
--- a/odb/mysql/makefile
+++ b/odb/mysql/makefile
@@ -11,7 +11,8 @@ connection-factory.cxx \
database.cxx \
exceptions.cxx \
transaction.cxx \
-transaction-impl.cxx
+transaction-impl.cxx \
+statement.cxx
cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
cxx_od := $(cxx_obj:.o=.o.d)
diff --git a/odb/mysql/statement.cxx b/odb/mysql/statement.cxx
new file mode 100644
index 0000000..68449ae
--- /dev/null
+++ b/odb/mysql/statement.cxx
@@ -0,0 +1,42 @@
+// file : odb/mysql/statement.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <new> // std::bad_alloc
+
+#include <odb/mysql/statement.hxx>
+#include <odb/mysql/connection.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ // statement
+ //
+
+ statement::
+ statement (connection& conn)
+ : conn_ (conn)
+ {
+ stmt_ = mysql_stmt_init (conn_.handle ());
+
+ if (stmt_ == 0)
+ throw std::bad_alloc ();
+ }
+
+ statement::
+ ~statement ()
+ {
+ mysql_stmt_close (stmt_);
+ }
+
+ // object_statements_base
+ //
+
+ object_statements_base::
+ ~object_statements_base ()
+ {
+ }
+ }
+}
diff --git a/odb/mysql/statement.hxx b/odb/mysql/statement.hxx
new file mode 100644
index 0000000..ab6ab9b
--- /dev/null
+++ b/odb/mysql/statement.hxx
@@ -0,0 +1,173 @@
+// file : odb/mysql/statement.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_STATEMENT_HXX
+#define ODB_MYSQL_STATEMENT_HXX
+
+#include <mysql/mysql.h>
+
+#include <map>
+#include <string>
+#include <typeinfo>
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+#include <odb/shared-ptr.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ class connection;
+
+ class statement: public shared_base
+ {
+ public:
+ virtual
+ ~statement () = 0;
+
+ protected:
+ statement (connection&);
+
+ protected:
+ connection& conn_;
+ MYSQL_STMT* stmt_;
+ };
+
+ template <typename T>
+ class insert_statement: public statement
+ {
+ public:
+ typedef T object_type;
+ typedef odb::object_traits<T> object_traits;
+ typedef typename object_traits::image_type image_type;
+
+ public:
+ virtual
+ ~insert_statement ();
+
+ insert_statement (connection& conn,
+ const std::string& query,
+ image_type&);
+
+ image_type&
+ image ()
+ {
+ return image_;
+ }
+
+ void
+ execute ();
+
+ private:
+ insert_statement (const insert_statement&);
+ insert_statement& operator= (const insert_statement&);
+
+ private:
+ image_type& image_;
+ MYSQL_BIND bind_[object_traits::column_count];
+ };
+
+ // Statement cache.
+ //
+
+ class object_statements_base: public shared_base
+ {
+ public:
+ virtual
+ ~object_statements_base ();
+
+ protected:
+ object_statements_base (connection& conn)
+ : conn_ (conn)
+ {
+ }
+
+ protected:
+ connection& conn_;
+ };
+
+ template <typename T>
+ class object_statements: public object_statements_base
+ {
+ public:
+ typedef typename object_traits<T>::image_type image_type;
+
+ object_statements (connection& conn)
+ : object_statements_base (conn)
+ {
+ }
+
+ insert_statement<T>&
+ insert ()
+ {
+ if (insert_ == 0)
+ insert_.reset (
+ new (shared) insert_statement<T> (
+ conn_, object_traits<T>::insert_query, image_));
+
+ return *insert_;
+ }
+
+ private:
+ image_type image_;
+ odb::shared_ptr<insert_statement<T> > insert_;
+ };
+
+ struct type_info_comparator
+ {
+ bool
+ operator() (const std::type_info* x, const std::type_info* y) const
+ {
+ // XL C++ on AIX has buggy type_info::before() in that
+ // it returns true for two different type_info objects
+ // that happened to be for the same type.
+ //
+#if defined(__xlC__) && defined(_AIX)
+ return *x != *y && x->before (*y);
+#else
+ return x->before (*y);
+#endif
+ }
+ };
+
+ class statement_cache
+ {
+ public:
+ statement_cache (connection& conn)
+ : conn_ (conn)
+ {
+ }
+
+ template <typename T>
+ object_statements<T>&
+ find ()
+ {
+ map::iterator i (map_.find (&typeid (T)));
+
+ if (i != map_.end ())
+ return static_cast<object_statements<T>&> (*i->second);
+
+ shared_ptr<object_statements<T> > p (
+ new (shared) object_statements<T> (conn_));
+
+ map_.insert (map::value_type (&typeid (T), p));
+ return *p;
+ }
+
+ private:
+ typedef std::map<const std::type_info*,
+ shared_ptr<object_statements_base>,
+ type_info_comparator> map;
+
+ connection& conn_;
+ map map_;
+ };
+ }
+}
+
+#include <odb/mysql/statement.txx>
+
+#endif // ODB_MYSQL_STATEMENT_HXX
diff --git a/odb/mysql/statement.txx b/odb/mysql/statement.txx
new file mode 100644
index 0000000..4f82942
--- /dev/null
+++ b/odb/mysql/statement.txx
@@ -0,0 +1,53 @@
+// file : odb/mysql/statement.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cstddef> // std::size_t
+#include <cstring> // std::memset
+
+#include <odb/mysql/exceptions.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ insert_statement<T>::
+ ~insert_statement ()
+ {
+ }
+
+ template <typename T>
+ insert_statement<T>::
+ insert_statement (connection& conn,
+ const std::string& query,
+ image_type& image)
+ : statement (conn), image_ (image)
+ {
+ if (mysql_stmt_prepare (stmt_, query.c_str (), query.size ()) != 0)
+ throw database_exception (stmt_);
+
+ std::memset (bind_, 0, sizeof (bind_));
+ }
+
+ template <typename T>
+ void insert_statement<T>::
+ execute ()
+ {
+ if (mysql_stmt_reset (stmt_))
+ throw database_exception (stmt_);
+
+ object_traits::bind (bind_, image_);
+
+ if (mysql_stmt_bind_param (stmt_, bind_))
+ throw database_exception (stmt_);
+
+ if (mysql_stmt_execute (stmt_))
+ throw database_exception (stmt_);
+
+ if (mysql_stmt_affected_rows (stmt_) != 1)
+ throw object_already_persistent ();
+ }
+ }
+}