diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-11-01 12:41:02 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-11-01 12:41:02 +0200 |
commit | 8bff3a2fc0ccce05abef7972beefadcd2534bdcd (patch) | |
tree | be6b6940abd472b3640f15e22c6f7d51ceee978e | |
parent | 59cab2f5fd95ed8ae833397044f2b704c3e7a8c4 (diff) |
Implement support for optimistic concurrency
New pragmas: optimistic, version. New test: optimistic. New database
function: reload().
-rw-r--r-- | odb/sqlite/object-statements.hxx | 75 | ||||
-rw-r--r-- | odb/sqlite/object-statements.txx | 21 | ||||
-rw-r--r-- | odb/sqlite/statement.cxx | 6 | ||||
-rw-r--r-- | odb/sqlite/statement.hxx | 3 |
4 files changed, 94 insertions, 11 deletions
diff --git a/odb/sqlite/object-statements.hxx b/odb/sqlite/object-statements.hxx index 53445b8..34a6a5e 100644 --- a/odb/sqlite/object-statements.hxx +++ b/odb/sqlite/object-statements.hxx @@ -106,6 +106,31 @@ namespace odb bool locked_; }; + template <typename T, bool optimistic> + struct optimistic_data; + + template <typename T> + struct optimistic_data<T, true> + { + typedef T object_type; + typedef odb::object_traits<object_type> object_traits; + + optimistic_data (bind*); + + // The id + optimistic column binding. + // + std::size_t id_image_version_; + binding id_image_binding_; + + details::shared_ptr<delete_statement> erase_; + }; + + template <typename T> + struct optimistic_data<T, false> + { + optimistic_data (bind*) {} + }; + template <typename T> 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& @@ -328,6 +364,23 @@ 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_)); + + od_.erase_->cached (true); + } + + return *od_.erase_; + } + // Container statement cache. // container_statement_cache_type& @@ -349,14 +402,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; @@ -364,6 +418,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_; @@ -385,12 +442,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. @@ -399,6 +460,10 @@ namespace odb std::size_t id_image_version_; binding id_image_binding_; + // Extra data for objects with optimistic concurrency support. + // + optimistic_data<T, managed_optimistic_column_count != 0> od_; + details::shared_ptr<insert_statement_type> persist_; details::shared_ptr<select_statement_type> find_; details::shared_ptr<update_statement_type> update_; diff --git a/odb/sqlite/object-statements.txx b/odb/sqlite/object-statements.txx index 7c5c178..7132296 100644 --- a/odb/sqlite/object-statements.txx +++ b/odb/sqlite/object-statements.txx @@ -17,6 +17,21 @@ namespace odb namespace sqlite { // + // optimistic_data + // + + template <typename T> + optimistic_data<T, true>:: + 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/sqlite/statement.cxx b/odb/sqlite/statement.cxx index a7ace7a..a33ebcb 100644 --- a/odb/sqlite/statement.cxx +++ b/odb/sqlite/statement.cxx @@ -389,7 +389,7 @@ namespace odb { } - void update_statement:: + unsigned long long update_statement:: execute () { bind_param (param_.bind, param_.count); @@ -410,8 +410,8 @@ namespace odb if (e != SQLITE_DONE) translate_error (e, conn_); - if (sqlite3_changes (conn_.handle ()) == 0) - throw object_not_persistent (); + return static_cast<unsigned long long> ( + sqlite3_changes (conn_.handle ())); } // delete_statement diff --git a/odb/sqlite/statement.hxx b/odb/sqlite/statement.hxx index 2bf770c..4fad1a3 100644 --- a/odb/sqlite/statement.hxx +++ b/odb/sqlite/statement.hxx @@ -311,7 +311,8 @@ namespace odb update_statement (connection& conn, const std::string& statement, binding& param); - void + + unsigned long long execute (); private: |