aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-11-01 12:41:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-11-01 12:41:02 +0200
commitcd4e72208fad964a22c99bb9fc15708a528a1e39 (patch)
tree91f7767d87601a66ef89cc901d1c334c30e961dc
parent8f49a9a3eddfbaa3afda78aad964268b31d0890b (diff)
Implement support for optimistic concurrency
New pragmas: optimistic, version. New test: optimistic. New database function: reload().
-rw-r--r--odb/mysql/object-statements.hxx73
-rw-r--r--odb/mysql/object-statements.txx21
-rw-r--r--odb/mysql/statement.cxx13
-rw-r--r--odb/mysql/statement.hxx3
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 <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 (MYSQL_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 (MYSQL_BIND*) {}
+ };
+
template <typename T>
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<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/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 <typename T>
+ optimistic_data<T, true>::
+ 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 <cassert>
-#include <odb/exceptions.hxx> // object_not_persistent
-
#include <odb/mysql/mysql.hxx>
#include <odb/mysql/statement.hxx>
#include <odb/mysql/connection.hxx>
@@ -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<my_ulonglong> (-1))
translate_error (conn_, stmt_);
+
+ return static_cast<unsigned long long> (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: