diff options
-rw-r--r-- | odb/mysql/connection.cxx | 2 | ||||
-rw-r--r-- | odb/mysql/connection.hxx | 11 | ||||
-rw-r--r-- | odb/mysql/makefile | 3 | ||||
-rw-r--r-- | odb/mysql/statement.cxx | 42 | ||||
-rw-r--r-- | odb/mysql/statement.hxx | 173 | ||||
-rw-r--r-- | odb/mysql/statement.txx | 53 |
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 (); + } + } +} |