summaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-09-05 13:02:10 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-09-05 13:02:10 +0200
commit654826cdafaac4199c8a8c90ef3396e312f0944f (patch)
tree5fb40bdbca960c426fe9d20a4450d89fc6250a7d /odb/relational
parent7e922ee487bad99ce3cad3a2b2bec8ac2b381c92 (diff)
Versioned section support
Diffstat (limited to 'odb/relational')
-rw-r--r--odb/relational/header.hxx47
-rw-r--r--odb/relational/inline.hxx41
-rw-r--r--odb/relational/pgsql/source.cxx26
-rw-r--r--odb/relational/processor.cxx6
-rw-r--r--odb/relational/source.cxx172
-rw-r--r--odb/relational/source.hxx226
6 files changed, 448 insertions, 70 deletions
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 3a4d244..12ed8ab 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -999,13 +999,21 @@ namespace relational
// copied at the end (update).
//
if (load || load_opt || update || update_opt)
+ {
os << "static std::size_t" << endl
<< "bind (" << bind_vector << "," << endl
<< "const " << bind_vector << " id," << endl
<< "std::size_t id_size," << endl
<< "image_type&," << endl
- << db << "::statement_kind);"
+ << db << "::statement_kind";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
<< endl;
+ }
// grow ()
//
@@ -1013,23 +1021,51 @@ namespace relational
// will have different number of elements.
//
if (generate_grow && (load || load_opt))
+ {
os << "static bool" << endl
- << "grow (image_type&, " << truncated_vector << ");"
+ << "grow (image_type&," << endl
+ << truncated_vector;
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
<< endl;
+ }
// init (object, image)
//
if (load)
+ {
os << "static void" << endl
- << "init (object_type&, const image_type&, database*);"
+ << "init (object_type&," << endl
+ << "const image_type&," << endl
+ << "database*";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
<< endl;
+ }
// init (image, object)
//
if (update)
+ {
os << "static " << (generate_grow ? "bool" : "void") << endl
- << "init (image_type&, const object_type&);"
+ << "init (image_type&," << endl
+ << "const object_type&";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration&";
+
+ os << ");"
<< endl;
+ }
// The rest does not apply to reuse-abstract sections.
//
@@ -1043,7 +1079,6 @@ namespace relational
// column_count
//
column_count_type const& cc (column_count (poly ? *poly_root : c_));
- bool versioned (force_versioned);
// Generate load and update column counts even when they are zero so
// that we can instantiate section_statements.
@@ -1061,7 +1096,7 @@ namespace relational
(update ? s.total - s.inverse - s.readonly : 0) << "UL;"
<< endl;
- os << "static const bool versioned = " << versioned << ";"
+ os << "static const bool versioned = " << s.versioned << ";"
<< endl;
// Statements.
diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx
index f5c5102..ed5081d 100644
--- a/odb/relational/inline.hxx
+++ b/odb/relational/inline.hxx
@@ -224,6 +224,12 @@ namespace relational
bool versioned (context::versioned (c));
+ // Schema name as a string literal or empty.
+ //
+ string schema_name (options.schema_name ()[db]);
+ if (!schema_name.empty ())
+ schema_name = strlit (schema_name);
+
string const& type (class_fq_name (c));
string traits ("access::object_traits_impl< " + type + ", id_" +
db.string () + " >");
@@ -413,18 +419,23 @@ namespace relational
{
os << "inline" << endl
<< "void " << traits << "::" << endl
- << "load_ (statements_type&," << endl
+ << "load_ (statements_type& sts," << endl
<< "object_type& obj," << endl
<< "bool";
if (versioned)
os << "," << endl
- << "const schema_version_migration&";
+ << "const schema_version_migration& svm";
os << ")"
<< "{"
- << "ODB_POTENTIALLY_UNUSED (obj);"
- << endl;
+ << "ODB_POTENTIALLY_UNUSED (sts);"
+ << "ODB_POTENTIALLY_UNUSED (obj);";
+
+ if (versioned)
+ os << "ODB_POTENTIALLY_UNUSED (svm);";
+
+ os << endl;
// Mark eager sections as loaded.
//
@@ -437,6 +448,28 @@ namespace relational
data_member& m (*i->member);
+ // If the section is soft- added or deleted, check the version.
+ // We can only end up here if the object itself is versioned
+ // (simple value section).
+ //
+ unsigned long long av (added (m));
+ unsigned long long dv (deleted (m));
+ if (av != 0 || dv != 0)
+ {
+ os << "if (";
+
+ if (av != 0)
+ os << "svm >= schema_version_migration (" << av << "ULL, true)";
+
+ if (av != 0 && dv != 0)
+ os << " &&" << endl;
+
+ if (dv != 0)
+ os << "svm <= schema_version_migration (" << dv << "ULL, true)";
+
+ os << ")" << endl;
+ }
+
// Section access is always by reference.
//
member_access& ma (m.get<member_access> ("get"));
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index 8a11914..a287dd2 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -312,6 +312,19 @@ namespace relational
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ // If the addition/deletion version is the same as the section's,
+ // then we don't need the test.
+ //
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
if (av != 0 || dv != 0)
{
os << "if (";
@@ -338,7 +351,18 @@ namespace relational
{
if (var_override_.empty ())
{
- if (added (mi.m) || deleted (mi.m))
+ unsigned long long av (added (mi.m));
+ unsigned long long dv (deleted (mi.m));
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
+ if (av != 0 || dv != 0)
os << "}";
}
diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx
index 3efeec4..231e4f0 100644
--- a/odb/relational/processor.cxx
+++ b/odb/relational/processor.cxx
@@ -1427,6 +1427,12 @@ namespace relational
}
}
+ // Handle forced versioning. When versioning is forced, ignore
+ // it for native views.
+ //
+ if (force_versioned && vq.kind == view_query::condition)
+ c.set ("versioned", true);
+
// Handle data members.
//
{
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 4008661..93b1035 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -1137,7 +1137,12 @@ traverse_object (type& c)
<< "throw abstract_class ();"
<< endl;
- if (versioned || persist_versioned_containers)
+ if (versioned ||
+ persist_versioned_containers ||
+ uss.count (user_sections::count_new |
+ user_sections::count_update |
+ user_sections::count_update_empty |
+ user_sections::count_versioned_only) != 0)
os << "const schema_version_migration& svm (" <<
"db.schema_version_migration (" << schema_name << "));";
@@ -1346,6 +1351,26 @@ traverse_object (type& c)
data_member& m (*i->member);
+ // If the section is soft- added or deleted, check the version.
+ //
+ unsigned long long av (added (m));
+ unsigned long long dv (deleted (m));
+ if (av != 0 || dv != 0)
+ {
+ os << "if (";
+
+ if (av != 0)
+ os << "svm >= schema_version_migration (" << av << "ULL, true)";
+
+ if (av != 0 && dv != 0)
+ os << " &&" << endl;
+
+ if (dv != 0)
+ os << "svm <= schema_version_migration (" << dv << "ULL, true)";
+
+ os << ")" << endl;
+ }
+
// Section access is always by reference.
//
member_access& ma (m.get<member_access> ("get"));
@@ -1387,12 +1412,28 @@ traverse_object (type& c)
// See if we have any sections that we might have to update.
//
bool sections (false);
+ bool versioned_sections (false);
for (user_sections::iterator i (uss.begin ()); i != uss.end (); ++i)
{
// This test will automatically skip the special version update section.
//
- if (!i->update_empty () && i->update != user_section::update_manual)
- sections = true;
+ if (i->update_empty () || i->update == user_section::update_manual)
+ continue;
+
+ sections = true;
+
+ if (added (*i->member) || deleted (*i->member))
+ versioned_sections = true;
+
+ // For change-updated sections, also check if we have any
+ // versioned smart containers.
+ //
+ if (i->update != user_section::update_change)
+ continue;
+
+ if (has_a (c, test_smart_container, &*i) !=
+ has_a (c, test_smart_container | exclude_deleted | exclude_added, &*i))
+ versioned_sections = true;
}
os << "void " << traits << "::" << endl
@@ -1449,14 +1490,16 @@ traverse_object (type& c)
<< endl;
}
- if ((versioned && update_columns) || update_versioned_containers)
+ if ((versioned && update_columns) ||
+ update_versioned_containers ||
+ versioned_sections)
os << "const schema_version_migration& svm (" <<
"db.schema_version_migration (" << schema_name << "));"
<< endl;
// If we have change-updated sections that contain change-tracking
// containers, then mark such sections as changed if any of the
- // containers was changed. Do this before calling the base so that
+ // containers were changed. Do this before calling the base so that
// we account for the whole hierarchy before we actually start
// updating any sections (important for optimistic concurrency
// version).
@@ -1474,11 +1517,29 @@ traverse_object (type& c)
data_member& m (*s.member);
os << "// " << m.name () << endl
- << "//" << endl
+ << "//" << endl;
- //@@ TODO version check.
+ // If the section is soft- added or deleted, check the version.
+ //
+ unsigned long long av (added (m));
+ unsigned long long dv (deleted (m));
+ if (av != 0 || dv != 0)
+ {
+ os << "if (";
- << "{";
+ if (av != 0)
+ os << "svm >= schema_version_migration (" << av << "ULL, true)";
+
+ if (av != 0 && dv != 0)
+ os << " &&" << endl;
+
+ if (dv != 0)
+ os << "svm <= schema_version_migration (" << dv << "ULL, true)";
+
+ os << ")";
+ }
+
+ os << "{";
// Section access is always by reference.
//
@@ -1852,6 +1913,27 @@ traverse_object (type& c)
//
data_member& m (*i->member);
+ // If the section is soft- added or deleted, check the version.
+ //
+ unsigned long long av (added (m));
+ unsigned long long dv (deleted (m));
+ if (av != 0 || dv != 0)
+ {
+ os << "if (";
+
+ if (av != 0)
+ os << "svm >= schema_version_migration (" << av << "ULL, true)";
+
+ if (av != 0 && dv != 0)
+ os << " &&" << endl;
+
+ if (dv != 0)
+ os << "svm <= schema_version_migration (" << dv << "ULL, true)";
+
+ os << ")"
+ << "{";
+ }
+
// Section access is always by reference.
//
member_access& ma (m.get<member_access> ("get"));
@@ -1938,6 +2020,9 @@ traverse_object (type& c)
}
os << "}";
+
+ if (av != 0 || dv != 0)
+ os << "}";
}
// Call callback (post_update).
@@ -3258,19 +3343,19 @@ traverse_object (type& c)
size_t load_containers (
has_a (c, test_container | include_eager_load, &main_section));
- bool load_versioned_containers (
- load_containers >
- has_a (c,
- test_container | include_eager_load |
- exclude_deleted | exclude_added | exclude_versioned,
- &main_section));
-
if (poly_derived ||
load_containers ||
uss.count (user_sections::count_new |
user_sections::count_load |
(poly ? user_sections::count_load_empty : 0)) != 0)
{
+ bool load_versioned_containers (
+ load_containers >
+ has_a (c,
+ test_container | include_eager_load |
+ exclude_deleted | exclude_added | exclude_versioned,
+ &main_section));
+
os << "void " << traits << "::" << endl
<< "load_ (statements_type& sts," << endl
<< "object_type& obj," << endl
@@ -3304,13 +3389,21 @@ traverse_object (type& c)
os << "extra_statement_cache_type& esc (sts.extra_statement_cache ());"
<< endl;
- if (load_containers)
+ if (!versioned && (
+ load_versioned_containers ||
+ uss.count (user_sections::count_new |
+ user_sections::count_load |
+ user_sections::count_load_empty |
+ user_sections::count_versioned_only) != 0))
{
- if (load_versioned_containers && !versioned)
- os << "const schema_version_migration& svm (" << endl
- << "sts.connection ().database ().schema_version_migration (" <<
- schema_name << "));";
+ os << "const schema_version_migration& svm (" << endl
+ << "sts.connection ().database ().schema_version_migration (" <<
+ schema_name << "));"
+ << endl;
+ }
+ if (load_containers)
+ {
instance<container_calls> t (container_calls::load_call, &main_section);
t->traverse (c);
}
@@ -3329,6 +3422,27 @@ traverse_object (type& c)
data_member& m (*i->member);
+ // If the section is soft- added or deleted, check the version.
+ //
+ unsigned long long av (added (m));
+ unsigned long long dv (deleted (m));
+ if (av != 0 || dv != 0)
+ {
+ os << "if (";
+
+ if (av != 0)
+ os << "svm >= schema_version_migration (" << av << "ULL, true)";
+
+ if (av != 0 && dv != 0)
+ os << " &&" << endl;
+
+ if (dv != 0)
+ os << "svm <= schema_version_migration (" << dv << "ULL, true)";
+
+ os << ")"
+ << "{";
+ }
+
// Section access is always by reference.
//
member_access& ma (m.get<member_access> ("get"));
@@ -3370,8 +3484,12 @@ traverse_object (type& c)
<< "}"
<< "else" << endl
// Reset to unloaded, unchanged state.
- << ma.translate ("obj") << ".reset ();"
- << endl;
+ << ma.translate ("obj") << ".reset ();";
+
+ if (av != 0 || dv != 0)
+ os << "}";
+ else
+ os << endl;
}
os << "}";
@@ -3398,17 +3516,17 @@ traverse_object (type& c)
<< "d = depth - d;" // Convert to distance from derived.
<< endl;
+ if (versioned)
+ os << "const schema_version_migration& svm (" <<
+ "db.schema_version_migration (" << schema_name << "));"
+ << endl;
+
// Avoid trying to execute an empty SELECT statement.
//
if (empty_depth != 0)
os << "if (d > " << (poly_depth - empty_depth) << "UL)"
<< "{";
- if (versioned)
- os << "const schema_version_migration& svm (" <<
- "db.schema_version_migration (" << schema_name << "));"
- << endl;
-
os << "if (!find_ (sts, 0" << (versioned ? ", svm" : "") << ", d))" << endl
<< "throw object_not_persistent ();" // Database inconsistency.
<< endl;
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 06d781f..1ea6d3f 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -1017,6 +1017,19 @@ namespace relational
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ // If the addition/deletion version is the same as the section's,
+ // then we don't need the test.
+ //
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
if (av != 0 || dv != 0)
{
os << "if (";
@@ -1046,7 +1059,18 @@ namespace relational
// We need to increment the index even if we skipped this
// member due to the schema version.
//
- if (added (mi.m) || deleted (mi.m))
+ unsigned long long av (added (mi.m));
+ unsigned long long dv (deleted (mi.m));
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
+ if (av != 0 || dv != 0)
os << "}";
if (semantics::class_* c = composite (mi.t))
@@ -1366,6 +1390,19 @@ namespace relational
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ // If the addition/deletion version is the same as the section's,
+ // then we don't need the test.
+ //
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
if (av != 0 || dv != 0)
{
os << "if (";
@@ -1570,7 +1607,18 @@ namespace relational
if (member_override_.empty ())
{
- if (added (mi.m) || deleted (mi.m))
+ unsigned long long av (added (mi.m));
+ unsigned long long dv (deleted (mi.m));
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
+ if (av != 0 || dv != 0)
os << "}";
}
}
@@ -1757,6 +1805,19 @@ namespace relational
//
unsigned long long av (added (mi.m));
unsigned long long dv (deleted (mi.m));
+
+ // If the addition/deletion version is the same as the section's,
+ // then we don't need the test.
+ //
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
if (av != 0 || dv != 0)
{
os << "if (";
@@ -3862,6 +3923,19 @@ namespace relational
//
unsigned long long av (added (member_path_));
unsigned long long dv (deleted (member_path_));
+
+ // If the addition/deletion version is the same as the section's,
+ // then we don't need the test.
+ //
+ if (user_section* s = dynamic_cast<user_section*> (section_))
+ {
+ if (av == added (*s->member))
+ av = 0;
+
+ if (dv == deleted (*s->member))
+ dv = 0;
+ }
+
if (av != 0 || dv != 0)
{
os << "if (";
@@ -4157,10 +4231,20 @@ namespace relational
<< "const " << bind_vector << (reuse_abst ? "," : " id,") << endl
<< "std::size_t" << (reuse_abst ? "," : " id_size,") << endl
<< "image_type& i," << endl
- << db << "::statement_kind sk)"
+ << db << "::statement_kind sk";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration& svm";
+
+ os << ")"
<< "{"
- << "ODB_POTENTIALLY_UNUSED (sk);"
- << endl
+ << "ODB_POTENTIALLY_UNUSED (sk);";
+
+ if (s.versioned)
+ os << "ODB_POTENTIALLY_UNUSED (svm);";
+
+ os << endl
<< "using namespace " << db << ";"
<< endl
<< "std::size_t n (0);"
@@ -4184,7 +4268,7 @@ namespace relational
<< "n += object_traits_impl< " << class_fq_name (*b.object) <<
", id_" << db << " >::" << public_name (*b.member) <<
"_traits::bind (" << endl
- << "b, 0, 0, i, sk);"
+ << "b, 0, 0, i, sk" << (b.versioned ? ", svm" : "") << ");"
<< endl;
}
@@ -4228,7 +4312,8 @@ namespace relational
<< "n += object_traits_impl< " << class_fq_name (*b->object) <<
", id_" << db << " >::" << public_name (*b->member) <<
"_traits::bind (" << endl
- << "b + n, 0, 0, *i" << acc << ", sk);"
+ << "b + n, 0, 0, *i" << acc << ", sk" <<
+ (b->versioned ? ", svm" : "") << ");"
<< endl;
}
@@ -4249,11 +4334,22 @@ namespace relational
if (generate_grow && (load || load_opt))
{
os << "bool " << scope << "::" << endl
- << "grow (image_type& i, " << truncated_vector << " t)"
+ << "grow (image_type& i," << endl
+ << truncated_vector << " t";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration& svm";
+
+ os << ")"
<< "{"
<< "ODB_POTENTIALLY_UNUSED (i);"
- << "ODB_POTENTIALLY_UNUSED (t);"
- << endl
+ << "ODB_POTENTIALLY_UNUSED (t);";
+
+ if (s.versioned)
+ os << "ODB_POTENTIALLY_UNUSED (svm);";
+
+ os << endl
<< "bool grew (false);"
<< endl;
@@ -4272,7 +4368,7 @@ namespace relational
<< "//" << endl
<< "grew = object_traits_impl< " << class_fq_name (*b.object) <<
", id_" << db << " >::" << public_name (*b.member) <<
- "_traits::grow (i, t);"
+ "_traits::grow (i, t" << (b.versioned ? ", svm" : "") << ");"
<< endl;
index += b.total + (load_opt ? 1 : 0);
@@ -4319,7 +4415,8 @@ namespace relational
<< "if (object_traits_impl< " << class_fq_name (*b->object) <<
", id_" << db << " >::" << public_name (*b->member) <<
"_traits::grow (" << endl
- << "*i" << acc << ", t + " << cols << "UL))" << endl
+ << "*i" << acc << ", t + " << cols << "UL" <<
+ (b->versioned ? ", svm" : "") << "))" << endl
<< "i" << acc << "->version++;"
<< endl;
}
@@ -4333,10 +4430,22 @@ namespace relational
if (load)
{
os << "void " << scope << "::" << endl
- << "init (object_type& o, const image_type& i, database* db)"
+ << "init (object_type& o," << endl
+ << "const image_type& i," << endl
+ << "database* db";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration& svm";
+
+ os << ")"
<< "{"
- << "ODB_POTENTIALLY_UNUSED (db);"
- << endl;
+ << "ODB_POTENTIALLY_UNUSED (db);";
+
+ if (s.versioned)
+ os << "ODB_POTENTIALLY_UNUSED (svm);";
+
+ os << endl;
if (s.base != 0)
{
@@ -4351,7 +4460,8 @@ namespace relational
<< "//" << endl
<< "object_traits_impl< " << class_fq_name (*b.object) <<
", id_" << db << " >::" << public_name (*b.member) <<
- "_traits::init (o, i, db);"
+ "_traits::init (o, i, db" <<
+ (b.versioned ? ", svm" : "") << ");"
<< endl;
}
else
@@ -4383,7 +4493,8 @@ namespace relational
<< "object_traits_impl< " << class_fq_name (*b->object) <<
", id_" << db << " >::" << public_name (*b->member) <<
"_traits::init (" << endl
- << "o, *i" << acc << ", db);"
+ << "o, *i" << acc << ", db" <<
+ (b->versioned ? ", svm" : "") << ");"
<< endl;
}
}
@@ -4402,9 +4513,21 @@ namespace relational
if (update)
{
os << (generate_grow ? "bool " : "void ") << scope << "::" << endl
- << "init (image_type& i, const object_type& o)"
- << "{"
- << "using namespace " << db << ";"
+ << "init (image_type& i," << endl
+ << "const object_type& o";
+
+ if (s.versioned)
+ os << "," << endl
+ << "const schema_version_migration& svm";
+
+ os << ")"
+ << "{";
+
+ if (s.versioned)
+ os << "ODB_POTENTIALLY_UNUSED (svm);"
+ << endl;
+
+ os << "using namespace " << db << ";"
<< endl
<< "statement_kind sk (statement_insert);"
<< "ODB_POTENTIALLY_UNUSED (sk);"
@@ -4430,7 +4553,7 @@ namespace relational
<< (generate_grow ? "grew = " : "") <<
"object_traits_impl< " << class_fq_name (*b.object) <<
", id_" << db << " >::" << public_name (*b.member) <<
- "_traits::init (i, o);"
+ "_traits::init (i, o" << (b.versioned ? ", svm" : "") << ");"
<< endl;
}
@@ -4454,8 +4577,13 @@ namespace relational
return;
}
- bool versioned (force_versioned);
- string sep (versioned ? "\n" : " ");
+ string sep (s.versioned ? "\n" : " ");
+
+ // Schema name as a string literal or empty.
+ //
+ string schema_name (options.schema_name ()[db]);
+ if (!schema_name.empty ())
+ schema_name = strlit (schema_name);
// Statements.
//
@@ -4613,6 +4741,12 @@ namespace relational
os << "ODB_POTENTIALLY_UNUSED (top);"
<< endl;
+ if (s.versioned || s.versioned_containers)
+ os << "const schema_version_migration& svm (" << endl
+ << "esc." << m.name () << ".connection ().database ()." <<
+ "schema_version_migration (" << schema_name << "));"
+ << endl;
+
// Load values, if any.
//
if (load || load_opt)
@@ -4683,15 +4817,23 @@ namespace relational
os << "if (" << ver << " != sts.select_image_version () ||" << endl
<< "imb.version == 0)"
<< "{"
- << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "bind (imb.bind, 0, 0, im, statement_select" <<
+ (s.versioned ? ", svm" : "") << ");"
<< "sts.select_image_version (" << ver << ");"
<< "imb.version++;"
<< "}";
// Id binding is assumed initialized and bound.
//
- os << "select_statement& st (sts.select_statement ());"
- << "st.execute ();"
+ os << "select_statement& st (sts.select_statement ());";
+
+ // The statement can be dynamically empty.
+ //
+ if (s.versioned)
+ os << "if (!st.empty ())"
+ << "{";
+
+ os << "st.execute ();"
<< "auto_result ar (st);"
<< "select_statement::result r (st.fetch ());"
<< endl;
@@ -4704,7 +4846,8 @@ namespace relational
{
os << "if (r == select_statement::truncated)"
<< "{"
- << "if (grow (im, sts.select_image_truncated ()))" << endl
+ << "if (grow (im, sts.select_image_truncated ()" <<
+ (s.versioned ? ", svm" : "") << "))" << endl
<< "im.version++;"
<< endl;
@@ -4716,7 +4859,8 @@ namespace relational
os << "if (" << ver << " != sts.select_image_version ())"
<< "{"
- << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "bind (imb.bind, 0, 0, im, statement_select" <<
+ (s.versioned ? ", svm" : "") << ");"
<< "sts.select_image_version (" << ver << ");"
<< "imb.version++;"
<< "st.refetch ();"
@@ -4752,11 +4896,15 @@ namespace relational
if (load)
{
- os << "init (obj, im, &sts.connection ().database ());";
+ os << "init (obj, im, &sts.connection ().database ()" <<
+ (s.versioned ? ", svm" : "") << ");";
init_value_extra (); // Stream results, etc.
os << endl;
}
+ if (s.versioned)
+ os << "}"; // if (!st.empty ())
+
if (poly)
os << "}"; // if (top)
}
@@ -4870,11 +5018,18 @@ namespace relational
<< endl;
}
+ if (s.versioned || s.readwrite_versioned_containers)
+ os << "const schema_version_migration& svm (" << endl
+ << "esc." << m.name () << ".connection ().database ()." <<
+ "schema_version_migration (" << schema_name << "));"
+ << endl;
+
// Update values, if any.
//
if (update || update_opt)
{
os << "using namespace " << db << ";"
+ << "using " << db << "::update_statement;" // Conflicts.
<< endl
<< "statements_type& sts (esc." << m.name () << ");"
<< endl
@@ -4888,7 +5043,7 @@ namespace relational
if (generate_grow)
os << "if (";
- os << "init (im, obj)";
+ os << "init (im, obj" << (s.versioned ? ", svm" : "") << ")";
if (generate_grow)
os << ")" << endl
@@ -4902,13 +5057,20 @@ namespace relational
<< "id.version != sts.update_id_binding_version () ||" << endl
<< "imb.version == 0)"
<< "{"
- << "bind (imb.bind, id.bind, id.count, im, statement_update);"
+ << "bind (imb.bind, id.bind, id.count, im, statement_update" <<
+ (s.versioned ? ", svm" : "") << ");"
<< "sts.update_image_version (im.version);"
<< "sts.update_id_binding_version (id.version);"
<< "imb.version++;"
<< "}";
- os << "if (sts.update_statement ().execute () == 0)" << endl;
+ os << "update_statement& st (sts.update_statement ());"
+ << "if (";
+
+ if (s.versioned)
+ os << "!st.empty () && ";
+
+ os << "st.execute () == 0)" << endl;
if (opt == 0)
os << "throw object_not_persistent ();";