From b8d34e12074a62d65575f22c0386d17db0e1a0b1 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/oracle/object-statements.hxx | 73 +++++++++++++++++++++++++++++++++++++--- odb/oracle/object-statements.txx | 21 ++++++++++-- odb/oracle/statement.cxx | 5 ++- odb/oracle/statement.hxx | 3 +- 4 files changed, 91 insertions(+), 11 deletions(-) diff --git a/odb/oracle/object-statements.hxx b/odb/oracle/object-statements.hxx index 8f469c7..095787f 100644 --- a/odb/oracle/object-statements.hxx +++ b/odb/oracle/object-statements.hxx @@ -107,6 +107,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 (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 (bind*) {} + }; + template class object_statements: public object_statements_base { @@ -257,6 +282,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& @@ -314,6 +350,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& @@ -335,14 +386,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; @@ -350,6 +402,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_; @@ -370,12 +425,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_; - bind update_image_bind_[update_column_count + id_column_count]; + 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. @@ -384,6 +443,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/oracle/object-statements.txx b/odb/oracle/object-statements.txx index c187c07..ffa8c46 100644 --- a/odb/oracle/object-statements.txx +++ b/odb/oracle/object-statements.txx @@ -17,6 +17,21 @@ namespace odb namespace oracle { // + // optimistic_data + // + + template + optimistic_data:: + optimistic_data (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/oracle/statement.cxx b/odb/oracle/statement.cxx index 0446353..85200ac 100644 --- a/odb/oracle/statement.cxx +++ b/odb/oracle/statement.cxx @@ -847,7 +847,7 @@ namespace odb bind_param (param.bind, param.count); } - void update_statement:: + unsigned long long update_statement:: execute () { OCIError* err (conn_.error_handle ()); @@ -879,8 +879,7 @@ namespace odb // UPDATE statment represents the number of matching rows found. Zero // indicates no match. // - if (row_count == 0) - throw object_not_persistent (); + return static_cast (row_count); } // diff --git a/odb/oracle/statement.hxx b/odb/oracle/statement.hxx index 0b56b8f..e0d30d9 100644 --- a/odb/oracle/statement.hxx +++ b/odb/oracle/statement.hxx @@ -176,7 +176,8 @@ namespace odb update_statement (connection& conn, const std::string& statement, binding& param); - void + + unsigned long long execute (); private: -- cgit v1.1