From 59e3ebcafb1dc4d54484143fc926ef8377bdb154 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 26 Nov 2014 15:04:56 +0200 Subject: Implement optimistic concurrency support in bulk operations Bulk update and SQL Server ROWVERSION not yet supported. --- common/bulk/driver.cxx | 190 +++++++++++++++++++++++++++++++++++++++++++++++++ common/bulk/test.hxx | 48 ++++++++++++- common/bulk/test.std | 8 +++ 3 files changed, 245 insertions(+), 1 deletion(-) 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 v (fill (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 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 v (fill (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 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 // HAVE_CXX11 +#include // HAVE_CXX11, DATABASE_* #include #include // 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 + -- cgit v1.1