diff options
Diffstat (limited to 'odb-tests/evolution/soft-add')
-rw-r--r-- | odb-tests/evolution/soft-add/buildfile | 64 | ||||
-rw-r--r-- | odb-tests/evolution/soft-add/driver.cxx | 2224 | ||||
-rw-r--r-- | odb-tests/evolution/soft-add/model.hxx | 504 | ||||
-rw-r--r-- | odb-tests/evolution/soft-add/test1.hxx | 9 | ||||
-rw-r--r-- | odb-tests/evolution/soft-add/test2.hxx | 11 | ||||
-rw-r--r-- | odb-tests/evolution/soft-add/test3.hxx | 11 | ||||
-rw-r--r-- | odb-tests/evolution/soft-add/testscript | 58 |
7 files changed, 2881 insertions, 0 deletions
diff --git a/odb-tests/evolution/soft-add/buildfile b/odb-tests/evolution/soft-add/buildfile new file mode 100644 index 0000000..6a61697 --- /dev/null +++ b/odb-tests/evolution/soft-add/buildfile @@ -0,0 +1,64 @@ +# file : evolution/soft-add/buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +if ($build.meta_operation != 'dist') + assert (!$multi) "multi-database mode is not supported by this test" + +db = ($databases[0]) + +import libodb = libodb%lib{odb} + +import libs = libodb-$db%lib{odb-$db} +import libs += lib{common} + +hdrs = test1 test2 test3 + +exe{driver}: {hxx cxx}{* -*-odb} testscript + +# Introduce the metadata library target to make sure the libodb library is +# resolved for the odb_compile ad hoc rule (see build/root.build for details). +# +libue{test-meta}: $libodb + +for h: $hdrs + exe{driver}: {hxx ixx cxx}{$h-odb}: hxx{$h} libue{test-meta} hxx{model} + +# Make sure testN.hxx are compiled serially since they share the changelog. +# +# @@ TODO: make order-only when supported by build2. +# +{hxx ixx cxx}{test3-odb}: {hxx ixx cxx}{test2-odb}: {hxx ixx cxx}{test1-odb} + +exe{driver}: libue{test-meta} $libs + +# Specify the ODB custom options to be used by the odb_compile ad hoc rule +# (see build/root.build for details). +# +odb_options = --table-prefix evo_soft_a_ \ + --schema-version-table evo_soft_a_sv \ + --generate-schema \ + --generate-query \ + --generate-prepared \ + --at-once \ + --changelog $out_base/model.xml + +<{hxx ixx cxx}{test1-odb}>: odb_options += --init-changelog +<{hxx ixx cxx}{test2-odb}>: odb_options += --omit-create --suppress-migration + +<{hxx ixx cxx}{test3-odb}>: +{ + odb_options += --omit-create + schema_versions = 002 003 +} + +cxx.poptions =+ "-I$out_base" "-I$src_base" + +# Testscript's run-time prerequisites. +# +exe{driver}: ../../alias{database-client}: include = adhoc + +testscript@./: +{ + db = $db + schemas = $hdrs +} diff --git a/odb-tests/evolution/soft-add/driver.cxx b/odb-tests/evolution/soft-add/driver.cxx new file mode 100644 index 0000000..3bd5f1f --- /dev/null +++ b/odb-tests/evolution/soft-add/driver.cxx @@ -0,0 +1,2224 @@ +// file : evolution/soft-add/driver.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// Test soft-add functionality. +// + +#include <memory> // std::unique_ptr +#include <iostream> + +#include <odb/database.hxx> +#include <odb/transaction.hxx> +#include <odb/schema-catalog.hxx> + +#include <libcommon/config.hxx> // DATABASE_XXX +#include <libcommon/common.hxx> + +#include "test2.hxx" +#include "test3.hxx" +#include "test2-odb.hxx" +#include "test3-odb.hxx" + +#undef NDEBUG +#include <cassert> + +using namespace std; +using namespace odb::core; + +int +main (int argc, char* argv[]) +{ + try + { + unique_ptr<database> db (create_database (argc, argv, false)); + + db->schema_version_table (quote_name ("evo_soft_a_sv")); + + bool embedded (schema_catalog::exists (*db)); + + // 1 - base version + // 2 - migration + // 3 - current version + // + unsigned short pass (*argv[argc - 1] - '0'); + + switch (pass) + { + case 1: + { + using namespace v3; // NOTE: not v2. + + if (embedded) + { + // SQLite has broken foreign keys when it comes to DDL. + // +#ifdef DATABASE_SQLITE + db->connection ()->execute ("PRAGMA foreign_keys=OFF"); +#endif + transaction t (db->begin ()); + schema_catalog::drop_schema (*db); + schema_catalog::create_schema (*db, "", false); + schema_catalog::migrate_schema (*db, 2); + t.commit (); + +#ifdef DATABASE_SQLITE + db->connection ()->execute ("PRAGMA foreign_keys=ON"); +#endif + } + + // Test basic soft-added member logic. + // + { + using namespace test2; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.str = "abc"; + o.num = 123; + o.vec.push_back (123); + o.ptr = new object1 (1); + o.ptr->ptrs.push_back (&o); + + transaction t (db->begin ()); + db->persist (o); + db->persist (*o.ptr); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->str == "" && p->num == 123 && + p->vec.empty () && p->ptr == 0); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && + i->str == "" && i->num == 123 && + i->vec.empty () && i->ptr == 0); + + try + { + db->query<object> (query::str.is_null ()); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + o.vec.push_back (234); + o.ptr = new object1 (2); + o.ptr->ptrs.push_back (&o); + + { + transaction t (db->begin ()); + db->persist (o); + db->persist (*o.ptr); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "" && p->num == 234 && + p->vec.empty () && p->ptr == 0); + t.commit (); + } + + o.str += 'e'; + o.num++; + o.vec.modify (0)++; + delete o.ptr; + o.ptr = 0; + + { + transaction t (db->begin ()); + db->erase<object1> (2); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "" && p->num == 235 && + p->vec.empty () && p->ptr == 0); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + // Test empty statement handling (INSERT, UPDATE). + // + { + using namespace test3; + + // None of the database operations should yet include the + // added members. + // + object o; + o.str = "bcd"; + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (o.id)); + assert (p->str == ""); + t.commit (); + } + + o.str += 'e'; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (o.id)); + assert (p->str == ""); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test empty statement handling (SELECT in polymorphic loader). + // + { + using namespace test4; + + // None of the database operations should yet include the + // added members. + // + object o (1); + o.str = "abc"; + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<base> p (db->load<base> (1)); + assert (static_cast<object&> (*p).str == ""); + db->erase (o); + t.commit (); + } + } + + // Test container with soft-added value member. + // + { + using namespace test5; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.vec.push_back (value ("abc", 123)); + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->vec[0].str == "" && p->vec[0].num == 123); + t.commit (); + } + + object o (2); + o.vec.push_back (value ("bcd", 234)); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->vec[0].str == "" && p->vec[0].num == 234); + t.commit (); + } + + o.vec.modify (0).str += 'e'; + o.vec.modify (0).num++; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->vec[0].str == "" && p->vec[0].num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + // Test view with soft-added member. + // + { + using namespace test6; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.str = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + typedef odb::query<view> query; + typedef odb::result<view> result; + + transaction t (db->begin ()); + result r (db->query<view> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "" && i->num == 123); + + try + { + db->query<object> (query::str == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + } + + // Test soft-added section member. + // + { + using namespace test7; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.str = "abc"; + o.num = 123; + o.vec.push_back (123); + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + + try + { + db->load (*p, p->s); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + o.str += 'e'; + o.num++; + o.vec.modify (0)++; + o.s.change (); + + { + transaction t (db->begin ()); + db->update (o); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + // Test soft-added members of a section. + // + { + using namespace test8; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.str = "abc"; + o.num = 123; + o.vec.push_back (123); + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->str == "" && p->num == 123 && p->vec.empty ()); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + assert (i->str == "" && i->num == 123 && i->vec.empty ()); + + try + { + db->query<object> (query::str == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "" && p->num == 234 && p->vec.empty ()); + t.commit (); + } + + o.str += 'e'; + o.num++; + o.vec.modify (0)++; // No longer automatically marked as changed. + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "" && p->num == 234 && p->vec.empty ()); + t.commit (); + } + + o.s.change (); + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "" && p->num == 235 && p->vec.empty ()); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + // Test basic soft-added member logic in polymorphic classes. + // + { + using namespace test9; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.bstr = "ab"; + o.dstr = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (static_cast<object*> (db->load<base> (1))); + assert (p->bstr == "" && p->dstr == "" && p->num == 123); + t.commit (); + } + + { + typedef odb::query<base> query; + typedef odb::result<base> result; + + transaction t (db->begin ()); + result r (db->query<base> (query::id == 1)); + result::iterator i (r.begin ()); + assert (i != r.end ()); + object& o (static_cast<object&> (*i)); + assert (o.bstr == "" && o.dstr == "" && o.num == 123); + + try + { + db->query<base> (query::bstr == "ab"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && + i->bstr == "" && i->dstr == "" && i->num); + + try + { + db->query<object> (query::dstr == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.bstr = "bc"; + o.dstr = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + assert (p->bstr == "" && p->dstr == "" && p->num == 234); + t.commit (); + } + + o.bstr += 'd'; + o.dstr += 'e'; + o.num++; + + { + transaction t (db->begin ()); + db->update (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + assert (p->bstr == "" && p->dstr == "" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<base> (2); + t.commit (); + } + } + + // Test soft-added section member in polymorphic classes. + // + { + using namespace test10; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.bstr = "ab"; + o.dstr = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<base> p (db->load<base> (1)); + + try + { + db->load (*p, p->s); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.bstr = "bc"; + o.dstr = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (static_cast<base&> (o)); + t.commit (); + } + + o.bstr += 'd'; + o.dstr += 'e'; + o.num++; + o.s.change (); + + { + transaction t (db->begin ()); + db->update (static_cast<base&> (o)); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<base> (2); + t.commit (); + } + } + + // Test soft-added members of a section in polymorphic classes. + // + { + using namespace test11; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.bstr = "ab"; + o.dstr = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<base> p (db->load<base> (1)); + db->load (*p, p->s); + object& o (static_cast<object&> (*p)); + assert (o.bstr == "" && o.dstr == "" && o.num == 123); + t.commit (); + } + + { + typedef odb::query<base> query; + typedef odb::result<base> result; + + transaction t (db->begin ()); + result r (db->query<base> (query::id == 1)); + result::iterator i (r.begin ()); + db->load (*i, i->s); + assert (i != r.end ()); + object& o (static_cast<object&> (*i)); + assert (o.bstr == "" && o.dstr == "" && o.num == 123); + + try + { + db->query<base> (query::bstr == "ab"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + db->load (*i, i->s); + assert (i != r.end () && + i->bstr == "" && i->dstr == "" && i->num); + + try + { + db->query<object> (query::dstr == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.bstr = "bc"; + o.dstr = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->bstr == "" && p->dstr == "" && p->num == 234); + t.commit (); + } + + o.bstr += 'd'; + o.dstr += 'e'; + o.num++; + o.s.change (); + + { + transaction t (db->begin ()); + db->update (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->bstr == "" && p->dstr == "" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<base> (2); + t.commit (); + } + + // Test empty statement detection in sections. + // + base b (3); + b.bstr = "bc"; + + { + transaction t (db->begin ()); + db->persist (b); + unique_ptr<base> p (db->load<base> (3)); + db->load (*p, p->s); + assert (p->bstr == ""); + t.commit (); + } + + b.bstr += 'd'; + b.s.change (); + + { + transaction t (db->begin ()); + db->update (b); + unique_ptr<base> p (db->load<base> (3)); + db->load (*p, p->s); + assert (p->bstr == ""); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (b); + t.commit (); + } + } + + // Test soft-added member and optimistic concurrency. + // + { + using namespace test12; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.str = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->str == "" && p->num == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "" && i->num == 123); + + try + { + db->query<object> (query::str == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "" && p->num == 234); + t.commit (); + } + + o.str += 'e'; + o.num++; + + { + transaction t (db->begin ()); + unsigned long long v (o.v_); + db->update (o); + assert (o.v_ != v); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "" && p->num == 235 && p->v_ == o.v_); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + // Test soft-added member in an object without id. + // + { + using namespace test13; + + typedef odb::query<object> query; + typedef odb::result<object> result; + + // None of the database operations should yet include the + // added members. + // + { + object o; + o.str = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "" && i->num == 123); + + try + { + db->query<object> (query::str == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o; + o.str = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (o); + + result r (db->query<object> (query::num == 234)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "" && i->num == 234); + + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase_query<object> (query::num == 234); + t.commit (); + } + } + + // Test soft-added member in an object with auto id. + // + { + using namespace test14; + + // None of the database operations should yet include the + // added members. + // + unsigned long id; + { + object o; + o.str = "abc"; + o.num = 123; + + transaction t (db->begin ()); + db->persist (o); + id = o.id; + t.commit (); + } + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (id)); + assert (p->str == "" && p->num == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "" && i->num == 123); + + try + { + db->query<object> (query::str == "abc"); // No such column. + assert (false); + } + catch (const odb::exception&) {} + + t.commit (); + } + + object o; + o.str = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (o.id)); + assert (p->str == "" && p->num == 234); + t.commit (); + } + + o.str += 'e'; + o.num++; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (o.id)); + assert (p->str == "" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (o.id); + t.commit (); + } + } + + // Test soft-added container member in a non-versioned object. + // + { + using namespace test21; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.num = 123; + o.vec.push_back (123); + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->num == 123 && p->vec.empty ()); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->num == 123 && i->vec.empty ()); + t.commit (); + } + + object o (2); + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->num == 234 && p->vec.empty ()); + t.commit (); + } + + o.num++; + o.vec.modify (0)++; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->num == 235 && p->vec.empty ()); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + // Test soft-added container member in a non-versioned section. + // + { + using namespace test22; + + // None of the database operations should yet include the + // added members. + // + { + object o (1); + o.num = 123; + o.vec.push_back (123); + + transaction t (db->begin ()); + db->persist (o); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->num == 123 && p->vec.empty ()); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + assert (i->num == 123 && i->vec.empty ()); + t.commit (); + } + + object o (2); + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->num == 234 && p->vec.empty ()); + t.commit (); + } + + o.num++; + o.vec.modify (0)++; // No longer automatically marks as changed. + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->num == 234 && p->vec.empty ()); + t.commit (); + } + + o.s.change (); + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->num == 235 && p->vec.empty ()); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase<object> (2); + t.commit (); + } + } + + break; + } + case 2: + { + using namespace v3; + + if (embedded) + { + transaction t (db->begin ()); + schema_catalog::migrate_schema_pre (*db, 3); + t.commit (); + } + + // Test basic soft-added member logic. + // + { + using namespace test2; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + p->str = "abc"; + p->vec.push_back (123); + delete p->ptr; + p->ptr = new object1 (1); + db->update (*p); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->str == "abc" && p->num == 123 && + p->vec[0] == 123 && p->ptr->id_ == 1); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::str.is_not_null () && + query::ptr->id == 1)); + result::iterator i (r.begin ()); + assert (i != r.end () && + i->str == "abc" && i->num == 123 && + i->vec[0] == 123 && i->ptr->id_ == 1); + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + o.vec.push_back (234); + o.ptr = new object1 (2); + o.ptr->ptrs.push_back (&o); + + { + transaction t (db->begin ()); + db->persist (o); + db->persist (*o.ptr); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "bcd" && p->num == 234 && + p->vec[0] == 234 && p->ptr->id_ == 2); + t.commit (); + } + + o.str += 'e'; + o.num++; + o.vec.modify (0)++; + delete o.ptr; + o.ptr = 0; + + { + transaction t (db->begin ()); + db->erase<object1> (2); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "bcde" && p->num == 235 && + p->vec[0] == 235 && p->ptr == 0); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test container with soft-added value member. + // + { + using namespace test5; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + p->vec.modify (0).str = "abc"; + db->update (*p); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->vec[0].str == "abc" && p->vec[0].num == 123); + t.commit (); + } + + object o (2); + o.vec.push_back (value ("bcd", 234)); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->vec[0].str == "bcd" && p->vec[0].num == 234); + t.commit (); + } + + o.vec.modify (0).str += 'e'; + o.vec.modify (0).num++; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->vec[0].str == "bcde" && p->vec[0].num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test view with soft-added member. + // + { + using namespace test6; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + p->str = "abc"; + db->update (*p); + t.commit (); + } + + { + typedef odb::query<view> query; + typedef odb::result<view> result; + + transaction t (db->begin ()); + result r (db->query<view> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + } + + // Test soft-added section member. + // + { + using namespace test7; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + p->str = "abc"; + p->vec.push_back (123); + db->update (*p, p->s); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->str == "abc" && p->num == 123 && p->vec[0] == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + assert (i->str == "abc" && i->num == 123 && i->vec[0] == 123); + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "bcd" && p->num == 234 && p->vec[0] == 234); + t.commit (); + } + + o.str += 'e'; + o.num++; + o.vec.modify (0)++; // Automatically marks section as updated. + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "bcde" && p->num == 235 && p->vec[0] == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test soft-added members of a section. + // + { + using namespace test8; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + p->str = "abc"; + p->vec.push_back (123); + db->update (*p, p->s); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->str == "abc" && p->num == 123 && p->vec[0] == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + assert (i->str == "abc" && i->num == 123 && i->vec[0] == 123); + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "bcd" && p->num == 234 && p->vec[0] == 234); + t.commit (); + } + + o.str += 'e'; + o.num++; + o.vec.modify (0)++; // Automatically marks section as updated. + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->str == "bcde" && p->num == 235 && p->vec[0] == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test basic soft-added member logic in polymorphic classes. + // + { + using namespace test9; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + p->bstr = "ab"; + p->dstr = "abc"; + db->update (*p); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (static_cast<object*> (db->load<base> (1))); + assert (p->bstr == "ab" && p->dstr == "abc" && p->num == 123); + t.commit (); + } + + { + typedef odb::query<base> query; + typedef odb::result<base> result; + + transaction t (db->begin ()); + result r (db->query<base> (query::bstr == "ab")); + result::iterator i (r.begin ()); + assert (i != r.end ()); + object& o (static_cast<object&> (*i)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + + object o (2); + o.bstr = "bc"; + o.dstr = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + assert (p->bstr == "bc" && p->dstr == "bcd" && p->num == 234); + t.commit (); + } + + o.bstr += 'd'; + o.dstr += 'e'; + o.num++; + + { + transaction t (db->begin ()); + db->update (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + assert (p->bstr == "bcd" && p->dstr == "bcde" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (static_cast<base&> (o)); + t.commit (); + } + } + + // Test soft-added section member in polymorphic classes. + // + { + using namespace test10; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + p->bstr = "ab"; + p->dstr = "abc"; + db->update (*p, p->s); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<base> p (db->load<base> (1)); + db->load (*p, p->s); + object& o (static_cast<object&> (*p)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + + { + typedef odb::query<base> query; + typedef odb::result<base> result; + + transaction t (db->begin ()); + result r (db->query<base> (query::bstr == "ab")); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + object& o (static_cast<object&> (*i)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + + object o (2); + o.bstr = "bc"; + o.dstr = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->bstr == "bc" && p->dstr == "bcd" && p->num == 234); + t.commit (); + } + + o.bstr += 'd'; + o.dstr += 'e'; + o.num++; + o.s.change (); + + { + transaction t (db->begin ()); + db->update (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->bstr == "bcd" && p->dstr == "bcde" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (static_cast<base&> (o)); + t.commit (); + } + } + + // Test soft-added members of a section in polymorphic classes. + // + { + using namespace test11; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + p->bstr = "ab"; + p->dstr = "abc"; + db->update (*p, p->s); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<base> p (db->load<base> (1)); + db->load (*p, p->s); + object& o (static_cast<object&> (*p)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + + { + typedef odb::query<base> query; + typedef odb::result<base> result; + + transaction t (db->begin ()); + result r (db->query<base> (query::bstr == "ab")); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + object& o (static_cast<object&> (*i)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + + object o (2); + o.bstr = "bc"; + o.dstr = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->bstr == "bc" && p->dstr == "bcd" && p->num == 234); + t.commit (); + } + + o.bstr += 'd'; + o.dstr += 'e'; + o.num++; + o.s.change (); + + { + transaction t (db->begin ()); + db->update (static_cast<base&> (o)); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->bstr == "bcd" && p->dstr == "bcde" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (static_cast<base&> (o)); + t.commit (); + } + } + + // Test soft-added member and optimistic concurrency. + // + { + using namespace test12; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + p->str = "abc"; + db->update (*p); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->str == "abc" && p->num == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + + object o (2); + o.str = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "bcd" && p->num == 234); + t.commit (); + } + + o.str += 'e'; + o.num++; + + { + transaction t (db->begin ()); + unsigned long long v (o.v_); + db->update (o); + assert (o.v_ != v); + unique_ptr<object> p (db->load<object> (2)); + assert (p->str == "bcde" && p->num == 235 && p->v_ == o.v_); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test soft-added member in an object without id. + // + { + using namespace test13; + + typedef odb::query<object> query; + typedef odb::result<object> result; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + + object o; + o.str = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (o); + + result r (db->query<object> (query::str == "bcd")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "bcd" && i->num == 234); + + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase_query<object> (query::str == "bcd"); + t.commit (); + } + } + + // Test soft-added member in an object with auto id. + // + { + using namespace test14; + + typedef odb::query<object> query; + typedef odb::result<object> result; + + // All the database operations should now include the added + // members. + // + unsigned long id; + { + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end ()); + i->str = "abc"; + db->update (*i); + id = i->id; + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (id)); + assert (p->str == "abc" && p->num == 123); + t.commit (); + } + + { + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + + object o; + o.str = "bcd"; + o.num = 234; + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (o.id)); + assert (p->str == "bcd" && p->num == 234); + t.commit (); + } + + o.str += 'e'; + o.num++; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (o.id)); + assert (p->str == "bcde" && p->num == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test soft-added container member in a non-versioned object. + // + { + using namespace test21; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + p->vec.push_back (123); + db->update (*p); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->num == 123 && p->vec[0] == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end () && i->num == 123 && i->vec[0] == 123); + t.commit (); + } + + object o (2); + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->num == 234 && p->vec[0] == 234); + t.commit (); + } + + o.num++; + o.vec.modify (0)++; + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + assert (p->num == 235 && p->vec[0] == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + // Test soft-added container member in a non-versioned section. + // + { + using namespace test22; + + // All the database operations should now include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + p->vec.push_back (123); + db->update (*p, p->s); + t.commit (); + } + + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->num == 123 && p->vec[0] == 123); + t.commit (); + } + + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::num == 123)); + result::iterator i (r.begin ()); + assert (i != r.end ()); + db->load (*i, i->s); + assert (i->num == 123 && i->vec[0] == 123); + t.commit (); + } + + object o (2); + o.num = 234; + o.vec.push_back (234); + + { + transaction t (db->begin ()); + db->persist (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->num == 234 && p->vec[0] == 234); + t.commit (); + } + + o.num++; + o.vec.modify (0)++; // Automatically marks section as changed. + + { + transaction t (db->begin ()); + db->update (o); + unique_ptr<object> p (db->load<object> (2)); + db->load (*p, p->s); + assert (p->num == 235 && p->vec[0] == 235); + t.commit (); + } + + { + transaction t (db->begin ()); + db->erase (o); + t.commit (); + } + } + + if (embedded) + { + transaction t (db->begin ()); + schema_catalog::migrate_schema_post (*db, 3); + t.commit (); + } + break; + } + case 3: + { + using namespace v3; + + // Test basic soft-added member logic. + // + { + using namespace test2; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->str == "abc" && p->num == 123 && + p->vec[0] == 123 && p->ptr->id_ == 1); + t.commit (); + } + } + + // Test container with soft-added value member. + // + { + using namespace test5; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->vec[0].str == "abc" && p->vec[0].num == 123); + t.commit (); + } + } + + // Test view with soft-added member. + // + { + using namespace test6; + + // All the database operations should still include the added + // members. + // + { + typedef odb::query<view> query; + typedef odb::result<view> result; + + transaction t (db->begin ()); + result r (db->query<view> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + } + + // Test soft-added section member. + // + { + using namespace test7; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->str == "abc" && p->num == 123 && p->vec[0] == 123); + t.commit (); + } + } + + // Test soft-added members of a section. + // + { + using namespace test8; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->str == "abc" && p->num == 123 && p->vec[0] == 123); + t.commit (); + } + } + + // Test basic soft-added member logic in polymorphic classes. + // + { + using namespace test9; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (static_cast<object*> (db->load<base> (1))); + assert (p->bstr == "ab" && p->dstr == "abc" && p->num == 123); + t.commit (); + } + } + + // Test soft-added section member in polymorphic classes. + // + { + using namespace test10; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<base> p (db->load<base> (1)); + db->load (*p, p->s); + object& o (static_cast<object&> (*p)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + } + + // Test soft-added members of a section in polymorphic classes. + // + { + using namespace test11; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<base> p (db->load<base> (1)); + db->load (*p, p->s); + object& o (static_cast<object&> (*p)); + assert (o.bstr == "ab" && o.dstr == "abc" && o.num == 123); + t.commit (); + } + } + + // Test soft-added member and optimistic concurrency. + // + { + using namespace test12; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->str == "abc" && p->num == 123); + t.commit (); + } + } + + // Test soft-added member in an object without id. + // + { + using namespace test13; + + typedef odb::query<object> query; + typedef odb::result<object> result; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + } + + // Test soft-added member in an object with auto id. + // + { + using namespace test14; + + // All the database operations should still include the added + // members. + // + { + typedef odb::query<object> query; + typedef odb::result<object> result; + + transaction t (db->begin ()); + result r (db->query<object> (query::str == "abc")); + result::iterator i (r.begin ()); + assert (i != r.end () && i->str == "abc" && i->num == 123); + t.commit (); + } + } + + // Test soft-added container member in a non-versioned object. + // + { + using namespace test21; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + assert (p->num == 123 && p->vec[0] == 123); + t.commit (); + } + } + + // Test soft-added container member in a non-versioned section. + // + { + using namespace test22; + + // All the database operations should still include the added + // members. + // + { + transaction t (db->begin ()); + unique_ptr<object> p (db->load<object> (1)); + db->load (*p, p->s); + assert (p->num == 123 && p->vec[0] == 123); + t.commit (); + } + } + + break; + } + default: + { + cerr << "unknown pass number '" << argv[argc - 1] << "'" << endl; + return 1; + } + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} diff --git a/odb-tests/evolution/soft-add/model.hxx b/odb-tests/evolution/soft-add/model.hxx new file mode 100644 index 0000000..39d63c4 --- /dev/null +++ b/odb-tests/evolution/soft-add/model.hxx @@ -0,0 +1,504 @@ +// file : evolution/soft-add/model.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef MODEL_VERSION +# error model.hxx included directly +#endif + +#include <string> + +#include <odb/core.hxx> +#include <odb/vector.hxx> +#include <odb/section.hxx> +#include <odb/lazy-ptr.hxx> + +#pragma db model version(1, MODEL_VERSION) + +#define MODEL_NAMESPACE_IMPL(V) v##V +#define MODEL_NAMESPACE(V) MODEL_NAMESPACE_IMPL(V) + +namespace MODEL_NAMESPACE(MODEL_VERSION) +{ + // The test numbers are made to correspond to the soft-delete ones. + // + + // Test basic soft-added member logic. + // + #pragma db namespace table("t2_") + namespace test2 + { + struct object; + + #pragma db object + struct object1 + { + object1 (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + odb::vector<odb::lazy_ptr<object> > ptrs; + }; + + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id), ptr (0) {} + ~object () {delete ptr;} + + #pragma db id + unsigned long id_; + + std::string str; + unsigned long num; + odb::vector<int> vec; + + #pragma db inverse(ptrs) + object1* ptr; + }; + +#if MODEL_VERSION == 3 + // Make it a LOB for Oracle and long data for SQL Server. + // + #pragma db member(object::str) added(3) \ + oracle:type("CLOB") \ + mssql:type("VARCHAR(max)") + #pragma db member(object::vec) added(3) + #pragma db member(object::ptr) added(3) +#else + #pragma db member(object::str) transient + #pragma db member(object::vec) transient + #pragma db member(object::ptr) transient +#endif + } + + // Test empty statement handling (INSERT, UPDATE). + // + #pragma db namespace table("t3_") + namespace test3 + { + #pragma db object + struct object + { + #pragma db id auto + unsigned long id; + + std::string str; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) +#else + #pragma db member(object::str) transient +#endif + } + + // Test empty statement handling (SELECT in polymorphic loader). + // + #pragma db namespace table("t4_") + namespace test4 + { + #pragma db object polymorphic + struct base + { + virtual + ~base () {} + base (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + }; + + #pragma db object + struct object: base + { + object (unsigned long id = 0): base (id) {} + + std::string str; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) +#else + #pragma db member(object::str) transient +#endif + } + + // Test container with soft-added value member. + // + #pragma db namespace table("t5_") + namespace test5 + { + #pragma db value + struct value + { + value () {} + value (const std::string& s, unsigned long n): str (s), num (n) {} + + std::string str; + unsigned long num; + }; + + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + odb::vector<value> vec; + }; + +#if MODEL_VERSION == 3 + #pragma db member(value::str) added(3) +#else + #pragma db member(value::str) transient +#endif + } + + // Test view with soft-added member. + // + #pragma db namespace table("t6_") + namespace test6 + { + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + std::string str; + unsigned long num; + }; + + #pragma db view object(object) + struct view + { + std::string str; + unsigned long num; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) + #pragma db member(view::str) added(3) +#else + #pragma db member(object::str) transient + #pragma db member(view::str) transient +#endif + } + + // Test soft-added section member. + // + #pragma db namespace table("t7_") + namespace test7 + { + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + +#if MODEL_VERSION == 3 + #pragma db load(lazy) update(change) added(3) + odb::section s; +#endif + + #pragma db section(s) + std::string str; + + unsigned long num; + + #pragma db section(s) + odb::vector<int> vec; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) section(s) + #pragma db member(object::vec) section(s) +#else + #pragma db member(object::str) transient + #pragma db member(object::vec) transient +#endif + } + + // Test soft-added members of a section. + // + #pragma db namespace table("t8_") + namespace test8 + { + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + #pragma db load(lazy) update(change) + odb::section s; + + std::string str; + + #pragma db section(s) + unsigned long num; + + odb::vector<int> vec; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) section(s) + #pragma db member(object::vec) added(3) section(s) +#else + #pragma db member(object::str) transient + #pragma db member(object::vec) transient +#endif + } + + // Test basic soft-added member logic in polymorphic classes. + // + #pragma db namespace table("t9_") + namespace test9 + { + #pragma db object polymorphic + struct base + { + virtual + ~base () {} + base (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + std::string bstr; + }; + + #pragma db object + struct object: base + { + object (unsigned long id = 0): base (id) {} + + std::string dstr; + unsigned long num; + }; + +#if MODEL_VERSION == 3 + #pragma db member(base::bstr) added(3) + #pragma db member(object::dstr) added(3) +#else + #pragma db member(base::bstr) transient + #pragma db member(object::dstr) transient +#endif + } + + // Test soft-added section member in polymorphic classes. + // + #pragma db namespace table("t10_") + namespace test10 + { + #pragma db object polymorphic + struct base + { + virtual + ~base () {} + base (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + +#if MODEL_VERSION == 3 + #pragma db load(lazy) update(change) added(3) + odb::section s; +#endif + + std::string bstr; + }; + + #pragma db object + struct object: base + { + object (unsigned long id = 0): base (id) {} + + std::string dstr; + unsigned long num; + }; + +#if MODEL_VERSION == 3 + #pragma db member(base::bstr) section(s) + #pragma db member(object::dstr) section(s) +#else + #pragma db member(base::bstr) transient + #pragma db member(object::dstr) transient +#endif + } + + // Test soft-added members of a section in polymorphic classes. + // + #pragma db namespace table("t11_") + namespace test11 + { + #pragma db object polymorphic + struct base + { + virtual + ~base () {} + base (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + #pragma db load(lazy) update(change) + odb::section s; + + std::string bstr; + }; + + #pragma db object + struct object: base + { + object (unsigned long id = 0): base (id) {} + + std::string dstr; + + #pragma db section(s) + unsigned long num; + }; + +#if MODEL_VERSION == 3 + #pragma db member(base::bstr) added(3) section(s) + #pragma db member(object::dstr) added(3) section(s) +#else + #pragma db member(base::bstr) transient + #pragma db member(object::dstr) transient +#endif + } + + // Test soft-added member and optimistic concurrency. + // + #pragma db namespace table("t12_") + namespace test12 + { + #pragma db object optimistic + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + #pragma db version mssql:type("ROWVERSION") + unsigned long long v_; + + std::string str; + unsigned long num; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) +#else + #pragma db member(object::str) transient +#endif + } + + // Test soft-added member in an object without id. + // + #pragma db namespace table("t13_") + namespace test13 + { + #pragma db object no_id + struct object + { + std::string str; + unsigned long num; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) default("abc") \ + mysql:type("VARCHAR(255)") +#else + #pragma db member(object::str) transient +#endif + } + + // Test soft-added member in an object with auto id. + // + #pragma db namespace table("t14_") + namespace test14 + { + #pragma db object + struct object + { + std::string str; + unsigned long num; + + #pragma db id auto + unsigned long id; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::str) added(3) +#else + #pragma db member(object::str) transient +#endif + } + + // Test soft-added container member in a non-versioned object. + // + #pragma db namespace table("t21_") + namespace test21 + { + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + unsigned long num; + odb::vector<int> vec; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::vec) added(3) +#else + #pragma db member(object::vec) transient +#endif + } + + // Test soft-added container member in a non-versioned section. + // + #pragma db namespace table("t22_") + namespace test22 + { + #pragma db object + struct object + { + object (unsigned long id = 0): id_ (id) {} + + #pragma db id + unsigned long id_; + + #pragma db load(lazy) update(change) + odb::section s; + + #pragma db section(s) + unsigned long num; + + odb::vector<int> vec; + }; + +#if MODEL_VERSION == 3 + #pragma db member(object::vec) added(3) section(s) +#else + #pragma db member(object::vec) transient +#endif + } +} + +#undef MODEL_NAMESPACE +#undef MODEL_NAMESPACE_IMPL diff --git a/odb-tests/evolution/soft-add/test1.hxx b/odb-tests/evolution/soft-add/test1.hxx new file mode 100644 index 0000000..461d663 --- /dev/null +++ b/odb-tests/evolution/soft-add/test1.hxx @@ -0,0 +1,9 @@ +// file : evolution/soft-add/test1.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST1_HXX +#define TEST1_HXX + +#pragma db model version(1, 1) + +#endif // TEST1_HXX diff --git a/odb-tests/evolution/soft-add/test2.hxx b/odb-tests/evolution/soft-add/test2.hxx new file mode 100644 index 0000000..746da4b --- /dev/null +++ b/odb-tests/evolution/soft-add/test2.hxx @@ -0,0 +1,11 @@ +// file : evolution/soft-add/test2.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST2_HXX +#define TEST2_HXX + +#define MODEL_VERSION 2 +#include "model.hxx" +#undef MODEL_VERSION + +#endif // TEST2_HXX diff --git a/odb-tests/evolution/soft-add/test3.hxx b/odb-tests/evolution/soft-add/test3.hxx new file mode 100644 index 0000000..f2990d0 --- /dev/null +++ b/odb-tests/evolution/soft-add/test3.hxx @@ -0,0 +1,11 @@ +// file : evolution/soft-add/test3.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TEST3_HXX +#define TEST3_HXX + +#define MODEL_VERSION 3 +#include "model.hxx" +#undef MODEL_VERSION + +#endif // TEST3_HXX diff --git a/odb-tests/evolution/soft-add/testscript b/odb-tests/evolution/soft-add/testscript new file mode 100644 index 0000000..5c26645 --- /dev/null +++ b/odb-tests/evolution/soft-add/testscript @@ -0,0 +1,58 @@ +# file : evolution/soft-add/testscript +# license : GNU GPL v2; see accompanying LICENSE file + +.include ../../database-options.testscript +.include ../../$db-schema.testscript + +test.arguments += $($(db)_options) + +: basics +: +if! $sqlite +{ + ss =; # Schema modification base file names. + + # Drop everything. + # + for s: $schemas + ss =+ $s + end; + + # Add base schema. + # + ss += test3-002-pre test3-002-post; + + # Add migration. + # + ss += test3-003-pre test3-003-post; + + # Run tests. + # + for s: $ss + f = $out_base/"$s".sql + + if $mysql + cat $f | $create_schema_cmd + elif $pgsql + $create_schema_cmd -f $f + elif $oracle + $create_schema_cmd "@$f" + elif $mssql + $create_schema_cmd -i $f + end + + if ($s == 'test3-002-post') + $* 1 + elif ($s == 'test3-003-pre') + $* 2 + elif ($s == 'test3-003-post') + $* 3 + end + end +} +else +{ + $* 1 &odb-test.db; + $* 2; + $* 3 +} |