aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2014-11-26 15:04:56 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2014-11-26 15:04:56 +0200
commit59e3ebcafb1dc4d54484143fc926ef8377bdb154 (patch)
treee832c9eff072039b19d8bf67e74d1796b03ff860
parent3d022058bc8b61c14c2d16e760ea1393d775c0d0 (diff)
Implement optimistic concurrency support in bulk operations
Bulk update and SQL Server ROWVERSION not yet supported.
-rw-r--r--common/bulk/driver.cxx190
-rw-r--r--common/bulk/test.hxx48
-rw-r--r--common/bulk/test.std8
3 files changed, 245 insertions, 1 deletions
diff --git a/common/bulk/driver.cxx b/common/bulk/driver.cxx
index 2903ae4..7d0b726 100644
--- a/common/bulk/driver.cxx
+++ b/common/bulk/driver.cxx
@@ -1015,6 +1015,196 @@ main (int argc, char* argv[])
}
}
+ // Test optimistic concurrency.
+ //
+ {
+ using namespace test7;
+
+ std::vector<object> v (fill<object> (4));
+
+ // persist
+ //
+ {
+ transaction t (db->begin ());
+ db->persist (v.begin (), v.end ());
+ t.commit ();
+
+ assert (v[0].v != 0 &&
+ v[1].v != 0 &&
+ v[2].v != 0 &&
+ v[3].v != 0);
+ }
+
+ // update
+ //
+ {
+ std::vector<object> c (v);
+
+ transaction t (db->begin ());
+ db->update (v.begin (), v.end ());
+ t.commit ();
+
+ assert (v[0].v > c[0].v &&
+ v[1].v > c[1].v &&
+ v[2].v > c[2].v &&
+ v[3].v > c[3].v);
+ }
+
+ {
+ object o2 (v[1]);
+ object o4 (v[3]);
+
+ o2.n++;
+ o4.n++;
+
+ transaction t (db->begin ());
+ db->update (o2);
+ db->update (o4);
+ t.commit ();
+ }
+
+ try
+ {
+ transaction t (db->begin ());
+ db->update (v.begin (), v.end ());
+ assert (false);
+ }
+ catch (const multiple_exceptions& e)
+ {
+ cout << e.what () << endl << endl;
+ }
+
+ // erase
+ //
+ try
+ {
+ transaction t (db->begin ());
+ db->erase (v.begin (), v.end ());
+ assert (false);
+ }
+ catch (const multiple_exceptions& e)
+ {
+ cout << e.what () << endl << endl;
+ }
+
+ {
+ transaction t (db->begin ());
+ db->reload (v[1]);
+ db->reload (v[3]);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ db->erase (v.begin (), v.end ());
+ t.commit ();
+ }
+ }
+
+ // Test SQL Server optimistic concurrency with ROWVERSION.
+ //
+#ifdef DATABASE_MSSQL
+ {
+ using namespace test8;
+
+ std::vector<object> v (fill<object> (4));
+
+ v[0].id = 1;
+ v[2].id = 2;
+ v[3].id = 3;
+ v[4].id = 4;
+
+
+ // persist
+ //
+ {
+ transaction t (db->begin ());
+ db->persist (v.begin (), v.end ());
+ t.commit ();
+
+ assert (v[0].v != 0 &&
+ v[1].v != 0 &&
+ v[2].v != 0 &&
+ v[3].v != 0);
+
+ //cerr << v[0].v << endl
+ // << v[0].v << endl
+ // << v[0].v << endl
+ // << v[0].v << endl;
+ }
+
+ // update
+ //
+
+ /*
+ {
+ std::vector<object> c (v);
+
+ transaction t (db->begin ());
+ db->update (v.begin (), v.end ());
+ t.commit ();
+
+ assert (v[0].v > c[0].v &&
+ v[1].v > c[1].v &&
+ v[2].v > c[2].v &&
+ v[3].v > c[3].v);
+ }
+ */
+
+ {
+ object o2 (v[1]);
+ object o4 (v[3]);
+
+ o2.n++;
+ o4.n++;
+
+ transaction t (db->begin ());
+ db->update (o2);
+ db->update (o4);
+ t.commit ();
+ }
+
+ /*
+ try
+ {
+ transaction t (db->begin ());
+ db->update (v.begin (), v.end ());
+ assert (false);
+ }
+ catch (const multiple_exceptions& e)
+ {
+ cout << e.what () << endl << endl;
+ }
+ */
+
+ // erase
+ //
+ try
+ {
+ transaction t (db->begin ());
+ db->erase (v.begin (), v.end ());
+ assert (false);
+ }
+ catch (const multiple_exceptions& e)
+ {
+ assert (e.attempted () == 4 && e.failed () == 4);
+ }
+
+ {
+ transaction t (db->begin ());
+ db->reload (v[1]);
+ db->reload (v[3]);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ db->erase (v.begin (), v.end ());
+ t.commit ();
+ }
+ }
+#endif
+
#endif
}
catch (const odb::exception& e)
diff --git a/common/bulk/test.hxx b/common/bulk/test.hxx
index 526762f..c0955f1 100644
--- a/common/bulk/test.hxx
+++ b/common/bulk/test.hxx
@@ -5,7 +5,7 @@
#ifndef TEST_HXX
#define TEST_HXX
-#include <common/config.hxx> // HAVE_CXX11
+#include <common/config.hxx> // HAVE_CXX11, DATABASE_*
#include <string>
#include <memory> // std::auto_ptr, std::unique_ptr
@@ -189,4 +189,50 @@ namespace test6
#endif
}
+// Test optimistic concurrency.
+//
+#pragma db namespace table("t7_")
+namespace test7
+{
+ #pragma db object optimistic bulk(3)
+ struct object
+ {
+ object (unsigned int n_ = 0, std::string s_ = "")
+ : id (0), v (0), n (n_), s (s_) {}
+
+ #pragma db id auto
+ unsigned long long id;
+
+ #pragma db version
+ unsigned long long v;
+
+ unsigned int n;
+ std::string s;
+ };
+}
+
+// Test SQL Server optimistic concurrency with ROWVERSION.
+//
+#ifdef DATABASE_MSSQL
+#pragma db namespace table("t8_")
+namespace test8
+{
+ #pragma db object optimistic bulk(3)
+ struct object
+ {
+ object (unsigned int n_ = 0, std::string s_ = "")
+ : id (0), v (0), n (n_), s (s_) {}
+
+ #pragma db id
+ unsigned long long id;
+
+ #pragma db version type("ROWVERSION")
+ unsigned long long v;
+
+ unsigned int n;
+ std::string s;
+ };
+}
+#endif
+
#endif // TEST_HXX
diff --git a/common/bulk/test.std b/common/bulk/test.std
index 6c4bdf9..e72869d 100644
--- a/common/bulk/test.std
+++ b/common/bulk/test.std
@@ -216,3 +216,11 @@ multiple exceptions, 10 elements attempted, 6 failed:
multiple exceptions, 3 elements attempted, 3 failed:
[0-2] (some) object not persistent
+multiple exceptions, 4 elements attempted, 4 failed:
+[0-2] (some) object changed concurrently
+[3] object changed concurrently
+
+multiple exceptions, 4 elements attempted, 4 failed:
+[0-2] (some) object changed concurrently
+[3] object changed concurrently
+