From cd4e72208fad964a22c99bb9fc15708a528a1e39 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 1 Nov 2011 12:41:02 +0200 Subject: Implement support for optimistic concurrency New pragmas: optimistic, version. New test: optimistic. New database function: reload(). --- odb/mysql/object-statements.hxx | 73 ++++++++++++++++++++++++++++++++++++++--- odb/mysql/object-statements.txx | 21 ++++++++++-- odb/mysql/statement.cxx | 13 +++----- odb/mysql/statement.hxx | 3 +- 4 files changed, 93 insertions(+), 17 deletions(-) diff --git a/odb/mysql/object-statements.hxx b/odb/mysql/object-statements.hxx index 0c20b1b..7991be6 100644 --- a/odb/mysql/object-statements.hxx +++ b/odb/mysql/object-statements.hxx @@ -106,6 +106,31 @@ namespace odb bool locked_; }; + template + struct optimistic_data; + + template + struct optimistic_data + { + typedef T object_type; + typedef odb::object_traits object_traits; + + optimistic_data (MYSQL_BIND*); + + // The id + optimistic column binding. + // + std::size_t id_image_version_; + binding id_image_binding_; + + details::shared_ptr erase_; + }; + + template + struct optimistic_data + { + optimistic_data (MYSQL_BIND*) {} + }; + template class object_statements: public object_statements_base { @@ -256,6 +281,17 @@ namespace odb binding& id_image_binding () {return id_image_binding_;} + // Optimistic id + managed column image binding. + // + std::size_t + optimistic_id_image_version () const {return od_.id_image_version_;} + + void + optimistic_id_image_version (std::size_t v) {od_.id_image_version_ = v;} + + binding& + optimistic_id_image_binding () {return od_.id_image_binding_;} + // Statements. // insert_statement_type& @@ -311,6 +347,21 @@ namespace odb return *erase_; } + delete_statement_type& + optimistic_erase_statement () + { + if (od_.erase_ == 0) + { + od_.erase_.reset ( + new (details::shared) delete_statement_type ( + conn_, + object_traits::optimistic_erase_statement, + od_.id_image_binding_)); + } + + return *od_.erase_; + } + // Container statement cache. // container_statement_cache_type& @@ -332,14 +383,15 @@ namespace odb private: // select = total - // insert = total - inverse - // update = total - inverse - id - readonly + // insert = total - inverse - managed_optimistic + // update = total - inverse - managed_optimistic - id - readonly // static const std::size_t select_column_count = object_traits::column_count; static const std::size_t insert_column_count = - object_traits::column_count - object_traits::inverse_column_count; + object_traits::column_count - object_traits::inverse_column_count - + object_traits::managed_optimistic_column_count; static const std::size_t update_column_count = insert_column_count - object_traits::id_column_count - object_traits::readonly_column_count; @@ -347,6 +399,9 @@ namespace odb static const std::size_t id_column_count = object_traits::id_column_count; + static const std::size_t managed_optimistic_column_count = + object_traits::managed_optimistic_column_count; + private: container_statement_cache_type container_statement_cache_; @@ -368,12 +423,16 @@ namespace odb // Update binding. Note that the id suffix is bound to id_image_ // below instead of image_ which makes this binding effectively // bound to two images. As a result, we have to track versions - // for both of them. + // for both of them. If this object uses optimistic concurrency, + // then the binding for the managed column (version, timestamp, + // etc) comes after the id and the image for such a column is + // stored as part of the id image. // std::size_t update_image_version_; std::size_t update_id_image_version_; binding update_image_binding_; - MYSQL_BIND update_image_bind_[update_column_count + id_column_count]; + MYSQL_BIND update_image_bind_[update_column_count + id_column_count + + managed_optimistic_column_count]; // Id image binding (only used as a parameter). Uses the suffix in // the update bind. @@ -382,6 +441,10 @@ namespace odb std::size_t id_image_version_; binding id_image_binding_; + // Extra data for objects with optimistic concurrency support. + // + optimistic_data od_; + details::shared_ptr persist_; details::shared_ptr find_; details::shared_ptr update_; diff --git a/odb/mysql/object-statements.txx b/odb/mysql/object-statements.txx index cf95a4a..34fa8f2 100644 --- a/odb/mysql/object-statements.txx +++ b/odb/mysql/object-statements.txx @@ -17,6 +17,21 @@ namespace odb namespace mysql { // + // optimistic_data + // + + template + optimistic_data:: + optimistic_data (MYSQL_BIND* b) + : id_image_binding_ ( + b, + object_traits::id_column_count + + object_traits::managed_optimistic_column_count) + { + id_image_version_ = 0; + } + + // // object_statements // @@ -34,9 +49,11 @@ namespace odb select_image_binding_ (select_image_bind_, select_column_count), insert_image_binding_ (insert_image_bind_, insert_column_count), update_image_binding_ (update_image_bind_, - update_column_count + id_column_count), + update_column_count + id_column_count + + managed_optimistic_column_count), id_image_binding_ (update_image_bind_ + update_column_count, - id_column_count) + id_column_count), + od_ (update_image_bind_ + update_column_count) { image_.version = 0; select_image_version_ = 0; diff --git a/odb/mysql/statement.cxx b/odb/mysql/statement.cxx index 7aa036d..4cd6f35 100644 --- a/odb/mysql/statement.cxx +++ b/odb/mysql/statement.cxx @@ -5,8 +5,6 @@ #include -#include // object_not_persistent - #include #include #include @@ -304,7 +302,7 @@ namespace odb translate_error (conn_, stmt_); } - void update_statement:: + unsigned long long update_statement:: execute () { conn_.clear (); @@ -325,13 +323,10 @@ namespace odb my_ulonglong r (mysql_stmt_affected_rows (stmt_)); - if (r > 0) - return; - - if (r == 0) - throw object_not_persistent (); - else + if (r == static_cast (-1)) translate_error (conn_, stmt_); + + return static_cast (r); } // delete_statement diff --git a/odb/mysql/statement.hxx b/odb/mysql/statement.hxx index 55850b6..ec128f2 100644 --- a/odb/mysql/statement.hxx +++ b/odb/mysql/statement.hxx @@ -165,7 +165,8 @@ namespace odb update_statement (connection& conn, const std::string& statement, binding& param); - void + + unsigned long long execute (); private: -- cgit v1.1