aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual.xhtml8
-rw-r--r--odb/context.cxx88
-rw-r--r--odb/context.hxx20
-rw-r--r--odb/header.cxx19
-rw-r--r--odb/inline.cxx30
-rw-r--r--odb/relational/header.cxx24
-rw-r--r--odb/relational/source.cxx382
-rw-r--r--odb/relational/source.hxx113
8 files changed, 293 insertions, 391 deletions
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index 92d0280..7b86be9 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -6238,7 +6238,13 @@ for (;;)
<p>For the interaction of change-tracking containers with change-updated
object sections, refer to <a href="#9.4">Section 9.4, "Sections and
- Change-Tracking Containers"</a>.</p>
+ Change-Tracking Containers"</a>. Note also that change-tracking
+ containers cannot be accessed with by-value accessors
+ (<a href="#14.4.5">Section 14.4.5,
+ "<code>get</code>/<code>set</code>/<code>access</code>"</a>)
+ since in certain situations such access may involve a
+ modification of the container (for example, clearing the change
+ flag after update).</p>
<h3><a name="5.4.1">5.4.1 Change-Tracking <code>vector</code></a></h3>
diff --git a/odb/context.cxx b/odb/context.cxx
index aa7c744..1ff906f 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -1376,6 +1376,94 @@ type_val_type (semantics::type& t,
return r;
}
+void context::
+set_member (semantics::data_member& m,
+ const string& obj,
+ const string& val,
+ const string& db,
+ const string& type)
+{
+ member_access& ma (m.get<member_access> ("set"));
+
+ // If this is a custom expression, output the location of where
+ // it came from.
+ //
+ if (!ma.synthesized)
+ os << "// From " << location_string (ma.loc, true) << endl;
+
+ if (ma.placeholder ())
+ {
+ // Cast the database to the concrete type this code is generated
+ // for. This way the user is free to use either the concrete or
+ // the common.
+ //
+ string d;
+ if (!db.empty ())
+ d = "static_cast<" + context::db.string () + "::database&> (" + db + ")";
+
+ os << ma.translate (obj, val, d) << ";";
+ }
+ else
+ {
+ // If this member is const and we have a synthesized direct access,
+ // then cast away constness. Otherwise, we assume that the user-
+ // provided expression handles this.
+ //
+ bool cast (!type.empty () && ma.direct () && const_member (m));
+ if (cast)
+ os << "const_cast< " << type << "& > (" << endl;
+
+ os << ma.translate (obj);
+
+ if (cast)
+ os << ")";
+
+ os << " = " << val << ";";
+ }
+}
+
+void context::
+inc_member (semantics::data_member& m,
+ const string& obj,
+ const string& gobj,
+ const string& type)
+{
+ member_access& ma (m.get<member_access> ("set"));
+
+ // If this is a custom expression, output the location of where
+ // it came from.
+ //
+ if (!ma.synthesized)
+ os << "// From " << location_string (ma.loc, true) << endl;
+
+ if (ma.placeholder ())
+ {
+ member_access& gma (m.get<member_access> ("get"));
+
+ if (!gma.synthesized)
+ os << "// From " << location_string (gma.loc, true) << endl;
+
+ os << ma.translate (obj, gma.translate (gobj) + " + 1") << ";";
+ }
+ else
+ {
+ // If this member is const and we have a synthesized direct access,
+ // then cast away constness. Otherwise, we assume that the user-
+ // provided expression handles this.
+ //
+ bool cast (ma.direct () && const_member (m));
+ if (cast)
+ os << "const_cast< " << type << "& > (" << endl;
+
+ os << ma.translate (obj);
+
+ if (cast)
+ os << ")";
+
+ os << "++;";
+ }
+}
+
data_member_path context::
resolve_data_members (semantics::class_& c,
const string& name,
diff --git a/odb/context.hxx b/odb/context.hxx
index e74aeb1..6646e93 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -324,8 +324,8 @@ struct member_access
//
std::string
translate (std::string const& obj,
- std::string const& val = std::string (),
- std::string const& db = std::string ()) const;
+ std::string const& val = std::string (),
+ std::string const& db = std::string ()) const;
location loc;
const char* kind; // accessor/modifier; used for diagnostics.
@@ -688,6 +688,22 @@ public:
bool make_const,
string const& var = "");
+ // Member access helpers. Database can be empty. If type is not empty,
+ // then it should be the non-cvr type of the member (e.g., id_type).
+ //
+ void
+ set_member (semantics::data_member& m,
+ const std::string& obj,
+ const std::string& val,
+ const std::string& db,
+ const std::string& type = "");
+
+ void
+ inc_member (semantics::data_member& m,
+ const std::string& sobj, // Set expression object.
+ const std::string& gobj, // Get expression object.
+ const std::string& type = "");
+
public:
// Resolve data member name in the form "a.b.c" to the data member path,
// issuing diagnostics and throwing operation_filed in case of an error.
diff --git a/odb/header.cxx b/odb/header.cxx
index f889ce9..0a01311 100644
--- a/odb/header.cxx
+++ b/odb/header.cxx
@@ -64,7 +64,7 @@ traverse_object (type& c)
bool auto_id (id && auto_ (*id));
bool base_id (id && &id->scope () != &c); // Comes from base.
- data_member* optimistic (context::optimistic (c));
+ data_member* opt (context::optimistic (c));
type* poly_root (polymorphic (c));
bool poly (poly_root != 0);
@@ -163,7 +163,7 @@ traverse_object (type& c)
os << "typedef object_traits< " << type << " >::id_type id_type;";
- if (optimistic != 0)
+ if (opt != 0)
os << "typedef object_traits< " << type << " >::version_type " <<
"version_type;";
@@ -183,10 +183,10 @@ traverse_object (type& c)
os << "typedef " << t.fq_name (hint) << " id_type;";
}
- if (optimistic != 0)
+ if (opt != 0)
{
semantics::names* hint;
- semantics::type& t (utype (*optimistic, hint));
+ semantics::type& t (utype (*opt, hint));
os << "typedef " << t.fq_name (hint) << " version_type;";
}
@@ -211,7 +211,7 @@ traverse_object (type& c)
os << "static const bool abstract = " << abst << ";"
<< endl;
- // id ()
+ // id()
//
if (id != 0 || !reuse_abst)
{
@@ -225,6 +225,15 @@ traverse_object (type& c)
<< endl;
}
+ // version()
+ //
+ if (opt != 0)
+ {
+ os << "static version_type" << endl
+ << "version (const object_type&);"
+ << endl;
+ }
+
// Query.
//
if (options.generate_query ())
diff --git a/odb/inline.cxx b/odb/inline.cxx
index 73b50c1..1af84b6 100644
--- a/odb/inline.cxx
+++ b/odb/inline.cxx
@@ -116,6 +116,8 @@ traverse_object (type& c)
bool auto_id (id && auto_ (*id));
bool base_id (id && &id->scope () != &c); // Comes from base.
+ data_member* opt (context::optimistic (c));
+
// Base class that contains the object id.
//
type* base (id != 0 && base_id ? dynamic_cast<type*> (&id->scope ()) : 0);
@@ -166,6 +168,34 @@ traverse_object (type& c)
os << "}";
}
+ if (opt != 0)
+ {
+ os << "inline" << endl
+ << traits << "::version_type" << endl
+ << traits << "::" << endl
+ << "version (const object_type& o)"
+ << "{";
+
+ if (base_id)
+ os << "return object_traits< " << class_fq_name (*base) <<
+ " >::version (o);";
+ else
+ {
+ // Get the id using the accessor expression. If this is not
+ // a synthesized expression, then output its location for
+ // easier error tracking.
+ //
+ member_access& ma (opt->get<member_access> ("get"));
+
+ if (!ma.synthesized)
+ os << "// From " << location_string (ma.loc, true) << endl;
+
+ os << "return " << ma.translate ("o") << ";";
+ }
+
+ os << "}";
+ }
+
// The rest does not apply to reuse-abstract objects.
//
if (reuse_abst)
diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx
index 4d68119..4b8b193 100644
--- a/odb/relational/header.cxx
+++ b/odb/relational/header.cxx
@@ -16,7 +16,7 @@ traverse_object (type& c)
bool auto_id (id && auto_ (*id));
bool base_id (id && &id->scope () != &c); // Comes from base.
- data_member* optimistic (context::optimistic (c));
+ data_member* opt (context::optimistic (c));
type* poly_root (polymorphic (c));
bool poly (poly_root != 0);
@@ -100,8 +100,8 @@ traverse_object (type& c)
discriminator_image_member_->traverse (*discriminator);
- if (optimistic != 0)
- version_image_member_->traverse (*optimistic);
+ if (opt != 0)
+ version_image_member_->traverse (*opt);
os << "std::size_t version;"
<< "};";
@@ -134,8 +134,8 @@ traverse_object (type& c)
id_image_member_->traverse (*id);
- if (optimistic != 0)
- version_image_member_->traverse (*optimistic);
+ if (opt != 0)
+ version_image_member_->traverse (*opt);
os << "std::size_t version;"
<< "};";
@@ -206,6 +206,10 @@ traverse_object (type& c)
os << "using object_traits<object_type>::id;"
<< endl;
+ if (opt != 0)
+ os << "using object_traits<object_type>::version;"
+ << endl;
+
if (!poly_derived && id != 0)
{
if (auto_id)
@@ -218,7 +222,7 @@ traverse_object (type& c)
<< "id (const image_type&);"
<< endl;
- if (optimistic != 0)
+ if (opt != 0)
os << "static version_type" << endl
<< "version (const image_type&);"
<< endl;
@@ -287,7 +291,7 @@ traverse_object (type& c)
{
os << "static void" << endl
<< "bind (" << bind_vector << ", id_image_type&" <<
- (optimistic != 0 ? ", bool bind_version = true" : "") << ");"
+ (opt != 0 ? ", bool bind_version = true" : "") << ");"
<< endl;
}
@@ -329,7 +333,7 @@ traverse_object (type& c)
{
os << "static void" << endl
<< "init (id_image_type&, const id_type&" <<
- (optimistic != 0 ? ", const version_type* = 0" : "") << ");"
+ (opt != 0 ? ", const version_type* = 0" : "") << ");"
<< endl;
}
@@ -465,7 +469,7 @@ traverse_object (type& c)
os << "static const char erase_statement[];";
- if (optimistic != 0 && !poly_derived)
+ if (opt != 0 && !poly_derived)
os << "static const char optimistic_erase_statement[];";
}
@@ -710,7 +714,7 @@ traverse_object (type& c)
<< "const id_type&," << endl
<< "discriminator_type*";
- if (optimistic != 0)
+ if (opt != 0)
os << "," << endl
<< "version_type* = 0";
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 97e7ea0..60d3b34 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -22,11 +22,8 @@ traverse_object (type& c)
data_member* id (id_member (c));
bool auto_id (id && auto_ (*id));
bool base_id (id && &id->scope () != &c); // Comes from base.
- member_access* id_ma (id ? &id->get<member_access> ("get") : 0);
data_member* opt (optimistic (c));
- member_access* opt_ma_get (opt ? &opt->get<member_access> ("get") : 0);
- member_access* opt_ma_set (opt ? &opt->get<member_access> ("set") : 0);
type* poly_root (polymorphic (c));
bool poly (poly_root != 0);
@@ -1283,34 +1280,8 @@ traverse_object (type& c)
if (!poly_derived && auto_id)
{
- member_access& ma (id->get<member_access> ("set"));
-
- if (!ma.synthesized)
- os << "// From " << location_string (ma.loc, true) << endl;
-
- if (ma.placeholder ())
- os << ma.translate (
- "obj", "id (sts.id_image ())",
- "static_cast<" + db.string () + "::database&> (db)") << ";"
- << endl;
- else
- {
- // If this member is const and we have a synthesized direct access,
- // then cast away constness. Otherwise, we assume that the user-
- // provided expression handles this.
- //
- bool cast (ma.direct () && const_member (*id));
- if (cast)
- os << "const_cast< id_type& > (" << endl;
-
- os << ma.translate ("obj");
-
- if (cast)
- os << ")";
-
- os << " = id (sts.id_image ());"
- << endl;
- }
+ set_member (*id, "obj", "id (sts.id_image ())", "db", "id_type");
+ os << endl;
}
// Set the optimistic concurrency version in the object member.
@@ -1319,33 +1290,12 @@ traverse_object (type& c)
{
// If we don't have auto id, then obj is a const reference.
//
- string obj (auto_id ? "obj" : "const_cast< object_type& > (obj)");
- string init (optimistic_version_init (*opt));
-
- if (!opt_ma_set->synthesized)
- os << "// From " << location_string (opt_ma_set->loc, true) << endl;
-
- if (opt_ma_set->placeholder ())
- os << opt_ma_set->translate (obj, init) << ";"
- << endl;
- else
- {
- // If this member is const and we have a synthesized direct access,
- // then cast away constness. Otherwise, we assume that the user-
- // provided expression handles this.
- //
- bool cast (opt_ma_set->direct () && const_member (*opt));
- if (cast)
- os << "const_cast< version_type& > (" << endl;
-
- os << opt_ma_set->translate (obj);
-
- if (cast)
- os << ")";
-
- os << " = " << init << ";"
- << endl;
- }
+ set_member (*opt,
+ (auto_id ? "obj" : "const_cast<object_type&> (obj)"),
+ optimistic_version_init (*opt),
+ "", // No database.
+ "version_type");
+ os << endl;
}
// Initialize id_image and binding if we are a root of a polymorphic
@@ -1361,12 +1311,8 @@ traverse_object (type& c)
os << "if (!top)"
<< "{";
- os << "id_image_type& i (sts.id_image ());";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "init (i, " << id_ma->translate ("obj") << ");"
+ os << "id_image_type& i (sts.id_image ());"
+ << "init (i, id (obj));"
<< endl
<< "binding& idb (sts.id_image_binding ());"
<< "if (i.version != sts.id_image_version () || idb.version == 0)"
@@ -1542,34 +1488,8 @@ traverse_object (type& c)
//
if (auto_id)
{
- member_access& ma (id->get<member_access> ("set"));
-
- if (!ma.synthesized)
- os << "// From " << location_string (ma.loc, true) << endl;
-
- if (ma.placeholder ())
- os << ma.translate (
- "obj", "id (sts.id_image (i))",
- "static_cast<" + db.string () + "::database&> (db)") << ";"
- << endl;
- else
- {
- // If this member is const and we have a synthesized direct access,
- // then cast away constness. Otherwise, we assume that the user-
- // provided expression handles this.
- //
- bool cast (ma.direct () && const_member (*id));
- if (cast)
- os << "const_cast< id_type& > (" << endl;
-
- os << ma.translate ("obj");
-
- if (cast)
- os << ")";
-
- os << " = id (sts.id_image (i));"
- << endl;
- }
+ set_member (*id, "obj", "id (sts.id_image (i))", "db", "id_type");
+ os << endl;
}
// Set the optimistic concurrency version.
@@ -1578,33 +1498,12 @@ traverse_object (type& c)
{
// If we don't have auto id, then obj is a const reference.
//
- string obj (auto_id ? "obj" : "const_cast< object_type& > (obj)");
- string init (optimistic_version_init (*opt, true));
-
- if (!opt_ma_set->synthesized)
- os << "// From " << location_string (opt_ma_set->loc, true) << endl;
-
- if (opt_ma_set->placeholder ())
- os << opt_ma_set->translate (obj, init) << ";"
- << endl;
- else
- {
- // If this member is const and we have a synthesized direct access,
- // then cast away constness. Otherwise, we assume that the user-
- // provided expression handles this.
- //
- bool cast (opt_ma_set->direct () && const_member (*opt));
- if (cast)
- os << "const_cast< version_type& > (" << endl;
-
- os << opt_ma_set->translate (obj);
-
- if (cast)
- os << ")";
-
- os << " = " << init << ";"
- << endl;
- }
+ set_member (*opt,
+ (auto_id ? "obj" : "const_cast<object_type&> (obj)"),
+ optimistic_version_init (*opt, true),
+ "", // No database.
+ "version_type");
+ os << endl;
}
// Reset sections: loaded, unchanged.
@@ -1878,12 +1777,8 @@ traverse_object (type& c)
os << "if (!top)";
os << "{"
- << "id_image_type& i (sts.id_image ());";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "init (i, " << id_ma->translate ("obj") << ");"
+ << "id_image_type& i (sts.id_image ());"
+ << "init (i, id (obj));"
<< endl;
os << "binding& idb (sts.id_image_binding ());"
@@ -1955,28 +1850,11 @@ traverse_object (type& c)
// Initialize id image.
//
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "const id_type& id (" << endl
- << id_ma->translate ("obj") << ");";
-
if (opt != 0)
- {
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "const version_type& v (" << endl
- << opt_ma_get->translate ("obj") << ");";
- }
+ os << "const version_type& v (version (obj));";
os << "id_image_type& idi (sts.id_image ());"
- << "init (idi, id";
-
- if (opt != 0)
- os << ", &v";
-
- os << ");"
+ << "init (idi, id (obj)" << (opt != 0 ? ", &v" : "") << ");"
<< endl;
// Initialize object image.
@@ -2075,12 +1953,8 @@ traverse_object (type& c)
os << "if (!top)";
os << "{"
- << "id_image_type& i (sts.id_image ());";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "init (i, " << id_ma->translate ("obj") << ");"
+ << "id_image_type& i (sts.id_image ());"
+ << "init (i, id (obj));"
<< endl;
os << "binding& idb (sts.id_image_binding ());"
@@ -2114,48 +1988,15 @@ traverse_object (type& c)
// Object is passed as const reference so we need to cast away
// constness.
//
- string obj ("const_cast< object_type& > (obj)");
+ const char* obj ("const_cast<object_type&> (obj)");
string inc (optimistic_version_increment (*opt));
- if (!opt_ma_set->synthesized)
- os << "// From " << location_string (opt_ma_set->loc, true) << endl;
-
- if (opt_ma_set->placeholder ())
- {
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) <<
- endl;
-
- if (inc == "1")
- os << opt_ma_set->translate (
- obj, opt_ma_get->translate ("obj") + " + 1") << ";";
- else
- os << opt_ma_set->translate (obj, inc) << ";";
-
- os << endl;
- }
+ if (inc == "1")
+ inc_member (*opt, obj, "obj", "version_type");
else
- {
- // If this member is const and we have a synthesized direct access,
- // then cast away constness. Otherwise, we assume that the user-
- // provided expression handles this.
- //
- bool cast (opt_ma_set->direct () && const_member (*opt));
- if (cast)
- os << "const_cast< version_type& > (" << endl;
-
- os << opt_ma_set->translate (obj);
-
- if (cast)
- os << ")";
-
- if (inc == "1")
- os << "++;";
- else
- os << " = " << inc << ";";
+ set_member (*opt, obj, inc, "", "version_type");
- os << endl;
- }
+ os << endl;
}
// Update sections that are loaded and need updating.
@@ -2240,17 +2081,8 @@ traverse_object (type& c)
//
if (opt != 0)
{
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "const version_type& v (" << endl
- << opt_ma_get->translate ("obj") << ");";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "init (sts.id_image (), " << id_ma->translate ("obj") <<
- ", &v);"
+ os << "const version_type& v (version (obj));"
+ << "init (sts.id_image (), id (obj), &v);"
<< endl;
}
@@ -2348,22 +2180,10 @@ traverse_object (type& c)
<< "const object_type& obj (*objs[i]);"
<< "callback (db, obj, callback_event::pre_update);";
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "const id_type& id (" << endl
- << id_ma->translate ("obj") << ");";
-
if (opt != 0)
- {
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
+ os << "const version_type& v (version (obj));";
- os << "const version_type& v (" << endl
- << opt_ma_get->translate ("obj") << ");";
- }
-
- os << "init (sts.id_image (i), id" << (opt != 0 ? ", &v" : "") << ");"
+ os << "init (sts.id_image (i), id (obj)" << (opt != 0 ? ", &v" : "") << ");"
//@@ assumption: generate_grow false
<< "init (sts.image (i), obj, statement_update);"
<< "}";
@@ -2433,48 +2253,15 @@ traverse_object (type& c)
// Object is passed as const reference so we need to cast away
// constness.
//
- string obj ("const_cast< object_type& > (obj)");
- string inc (optimistic_version_increment (*opt, true));
+ const char* obj ("const_cast<object_type&> (obj)");
+ string inc (optimistic_version_increment (*opt));
- if (!opt_ma_set->synthesized)
- os << "// From " << location_string (opt_ma_set->loc, true) << endl;
-
- if (opt_ma_set->placeholder ())
- {
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) <<
- endl;
-
- if (inc == "1")
- os << opt_ma_set->translate (
- obj, opt_ma_get->translate ("obj") + " + 1") << ";";
- else
- os << opt_ma_set->translate (obj, inc) << ";";
-
- os << endl;
- }
+ if (inc == "1")
+ inc_member (*opt, obj, "obj", "version_type");
else
- {
- // If this member is const and we have a synthesized direct access,
- // then cast away constness. Otherwise, we assume that the user-
- // provided expression handles this.
- //
- bool cast (opt_ma_set->direct () && const_member (*opt));
- if (cast)
- os << "const_cast< version_type& > (" << endl;
+ set_member (*opt, obj, inc, "", "version_type");
- os << opt_ma_set->translate (obj);
-
- if (cast)
- os << ")";
-
- if (inc == "1")
- os << "++;";
- else
- os << " = " << inc << ";";
-
- os << endl;
- }
+ os << endl;
}
os << "callback (db, obj, callback_event::post_update);"
@@ -2745,11 +2532,7 @@ traverse_object (type& c)
if (!abst || erase_containers)
{
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "const id_type& id (" << endl
- << id_ma->translate ("obj") << ");"
+ os << "const id_type& id (object_traits_impl::id (obj));"
<< endl;
}
@@ -2820,11 +2603,7 @@ traverse_object (type& c)
os << "if (top)"
<< "{";
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "const version_type& v (" << endl
- << opt_ma_get->translate ("obj") << ");"
+ os << "const version_type& v (version (obj));"
<< "id_image_type& i (" << rsts << ".id_image ());"
<< "init (i, id, &v);"
<< endl;
@@ -2862,10 +2641,7 @@ traverse_object (type& c)
<< "root_traits::discriminator_ (" << rsts << ", id, 0, &v);"
<< endl;
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "if (v != " << opt_ma_get->translate ("obj") << ")" << endl
+ os << "if (v != version (obj))" << endl
<< "throw object_changed ();"
<< "}";
}
@@ -2906,11 +2682,7 @@ traverse_object (type& c)
os << "sts.find_statement ().free_result ();"
<< endl;
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "if (version (sts.image ()) != " <<
- opt_ma_get->translate ("obj") << ")" << endl
+ os << "if (version (sts.image ()) != version (obj))" << endl
<< "throw object_changed ();"
<< endl;
}
@@ -3034,21 +2806,9 @@ traverse_object (type& c)
<< "for (std::size_t i (0); i != n; ++i)"
<< "{"
<< "const object_type& obj (*objs[i]);"
- << "callback (db, obj, callback_event::pre_erase);";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "const id_type& id (" << endl
- << id_ma->translate ("obj") << ");";
-
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "const version_type& v (" << endl
- << opt_ma_get->translate ("obj") << ");";
-
- os << "init (sts.id_image (i), id, &v);"
+ << "callback (db, obj, callback_event::pre_erase);"
+ << "const version_type& v (version (obj));"
+ << "init (sts.id_image (i), id (obj), &v);"
<< "}";
os << "binding& idb (sts.id_image_binding ());"
@@ -3080,14 +2840,8 @@ traverse_object (type& c)
<< "if (mex.fatal ())" << endl // Don't do any extra work.
<< "continue;"
<< endl
- << "const object_type& obj (*objs[i]);";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "const id_type& id (" << endl
- << id_ma->translate ("obj") << ");"
- << "pointer_cache_traits::erase (db, id);"
+ << "const object_type& obj (*objs[i]);"
+ << "pointer_cache_traits::erase (db, id (obj));"
<< "callback (db, obj, callback_event::post_erase);"
<< "}"; // for
}
@@ -3445,14 +3199,8 @@ traverse_object (type& c)
<< "statements_type::auto_lock l (" << rsts << ");"
<< endl;
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "const id_type& id (" << endl
- << id_ma->translate ("obj") << ");"
- << endl;
-
- os << "if (!find_ (sts, &id" <<
+ os << "const id_type& id (object_traits_impl::id (obj));"
+ << "if (!find_ (sts, &id" <<
(versioned ? ", svm" : "") << "))" << endl
<< "return false;"
<< endl;
@@ -3468,12 +3216,10 @@ traverse_object (type& c)
if (opt != 0)
{
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
+ const char* tr (poly_derived ? "root_traits::" : "");
- os << "if (" << (poly_derived ? "root_traits::" : "") << "version (" <<
- rsts << ".image ()) == " << opt_ma_get->translate ("obj") <<
- ")" << endl
+ os << "if (" << tr << "version (" << rsts << ".image ()) == " <<
+ tr << "version (obj))" << endl
<< "return true;"
<< endl;
}
@@ -3558,12 +3304,8 @@ traverse_object (type& c)
// Initialize id image. This is not necessarily the root of the
// polymorphic hierarchy.
//
- os << "id_image_type& i (sts.id_image ());";
-
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "init (i, " << id_ma->translate ("obj") << ");"
+ os << "id_image_type& i (sts.id_image ());"
+ << "init (i, id (obj));"
<< endl;
os << "binding& idb (sts.id_image_binding ());"
@@ -3698,21 +3440,11 @@ traverse_object (type& c)
// polymorphic hierarchy.
//
if (opt != 0)
- {
- if (!opt_ma_get->synthesized)
- os << "// From " << location_string (opt_ma_get->loc, true) << endl;
-
- os << "const version_type& v (" << endl
- << opt_ma_get->translate ("obj") << ");";
- }
+ os << "const version_type& v (version (obj));";
os << "id_image_type& i (sts.id_image ());";
- if (!id_ma->synthesized)
- os << "// From " << location_string (id_ma->loc, true) << endl;
-
- os << "init (i, " << id_ma->translate ("obj") <<
- (opt != 0 ? ", &v" : "") << ");"
+ os << "init (i, id (obj)" << (opt != 0 ? ", &v" : "") << ");"
<< endl;
os << "binding& idb (sts.id_image_binding ());"
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 56949d6..a160672 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -3206,7 +3206,7 @@ namespace relational
: p);
if (poly_derived)
- // This pointer could have from from cache, so use dynamic
+ // This pointer could have come from cache, so use dynamic
// cast.
//
r = p_tr + "::dynamic_pointer_cast<" + o_tp + "> (\n" +
@@ -3232,15 +3232,7 @@ namespace relational
<< "// member cannot be initialized from an object pointer.\n"
<< "//" << endl;
- if (!ma.synthesized)
- os << "// From " << location_string (ma.loc, true) << endl;
-
- if (ma.placeholder ())
- os << ma.translate (
- "o", r, "*static_cast<" + db.string () + "::database*> (db)")
- << ";";
- else
- os << ma.translate ("o") << " = " << r << ";";
+ set_member (mi.m, "o", r, "db");
}
if (mp_raw && !poly)
@@ -3248,15 +3240,7 @@ namespace relational
if (!op_raw)
os << "else" << endl; // NULL p
- if (!ma.synthesized)
- os << "// From " << location_string (ma.loc, true) << endl;
-
- if (ma.placeholder ())
- os << ma.translate (
- "o", o, "*static_cast<" + db.string () + "::database*> (db)")
- << ";";
- else
- os << ma.translate ("o") << " = " << o << ";";
+ set_member (mi.m, "o", o, "db");
}
}
}
@@ -5002,7 +4986,7 @@ namespace relational
: object_members_base (true, false, true, false, section),
call_ (call),
obj_prefix_ ("obj"),
- modifier_ (0)
+ by_value_ (0)
{
}
@@ -5032,7 +5016,9 @@ namespace relational
semantics::class_& c,
semantics::type* w)
{
- if (m == 0 || call_ == erase_id_call || modifier_ != 0)
+ if (m == 0 ||
+ call_ == erase_id_call ||
+ (call_ == load_call && by_value_ != 0))
{
object_members_base::traverse_composite (m, c);
return;
@@ -5049,14 +5035,22 @@ namespace relational
// are just going to set a flag that can be checked in
// traverse_container() below.
//
- if (ma.placeholder ())
+ if (call_ == load_call && ma.placeholder ())
{
- modifier_ = &ma;
+ by_value_ = &ma;
object_members_base::traverse_composite (m, c);
- modifier_ = 0;
+ by_value_ = 0;
return;
}
+ // We also don't support by-value accessors is there is a
+ // smart container inside (which, again, we don't know at
+ // this point). So keep track of such first instance.
+ //
+ member_access* old_by_value (by_value_);
+ if (call_ != load_call && ma.by_value && by_value_ == 0)
+ by_value_ = &ma;
+
string old_op (obj_prefix_);
string old_f (from_);
obj_prefix_.clear ();
@@ -5065,8 +5059,7 @@ namespace relational
// access, then cast away constness. Otherwise, we assume
// that the user-provided expression handles this.
//
- bool cast (
- call_ == load_call && ma.direct () && const_member (*m));
+ bool cast (call_ == load_call && ma.direct () && const_member (*m));
if (cast)
obj_prefix_ = "const_cast< " + member_ref_type (*m, false) +
" > (\n";
@@ -5103,6 +5096,7 @@ namespace relational
object_members_base::traverse_composite (m, c);
from_ = old_f;
obj_prefix_ = old_op;
+ by_value_ = old_by_value;
}
virtual void
@@ -5137,15 +5131,37 @@ namespace relational
// We don't support by-value modifiers for composite values
// with containers.
//
- if (call_ == load_call && modifier_ != 0)
+ if (call_ == load_call && by_value_ != 0)
{
- error (modifier_->loc) << "by-value modification of a composite "
+ error (by_value_->loc) << "by-value modification of a composite "
<< "value with container is not supported"
<< endl;
info (m.location ()) << "container member is defined here" << endl;
throw operation_failed ();
}
+ // We don't support by-value accessors for smart containers.
+ //
+ if (call_ != load_call && smart)
+ {
+ if (by_value_ != 0)
+ {
+ error (by_value_->loc) << "by-value access to a composite value "
+ << "with smart container is not supported"
+ << endl;
+ info (m.location ()) << "container member is defined here" << endl;
+ throw operation_failed ();
+ }
+
+ if (ma.by_value)
+ {
+ error (ma.loc) << "by-value access to a smart container is not "
+ << "supported" << endl;
+ info (m.location ()) << "container member is defined here" << endl;
+ throw operation_failed ();
+ }
+ }
+
// If the member is soft- added or deleted, check the version.
//
unsigned long long av (added (member_path_));
@@ -5179,28 +5195,30 @@ namespace relational
os << ")" << endl;
}
+ os << "{";
+
if (call_ != erase_id_call && (call_ != erase_obj_call || smart))
{
- os << "{";
-
- // Output stored locations, if any.
- //
- if (!ma.placeholder ())
- os << from_;
-
- // If this is not a synthesized expression, then output its
- // location for easier error tracking.
- //
- if (!ma.synthesized)
- os << "// From " << location_string (ma.loc, true) << endl;
-
// See if we are modifying via a reference or proper modifier.
//
- if (ma.placeholder ())
+ if (call_ == load_call && ma.placeholder ())
os << member_val_type (m, false, "v") << ";"
<< endl;
else
{
+ // Note: this case is for both access and modification.
+ //
+
+ // Output stored locations, if any.
+ //
+ os << from_;
+
+ // If this is not a synthesized expression, then output its
+ // location for easier error tracking.
+ //
+ if (!ma.synthesized)
+ os << "// From " << location_string (ma.loc, true) << endl;
+
// VC++ cannot grok the constructor syntax.
//
os << member_ref_type (m, call_ != load_call, "v") << " =" << endl
@@ -5210,8 +5228,7 @@ namespace relational
// access, then cast away constness. Otherwise, we assume
// that the user-provided expression handles this.
//
- bool cast (
- call_ == load_call && ma.direct () && const_member (m));
+ bool cast (call_ == load_call && ma.direct () && const_member (m));
if (cast)
os << "const_cast< " << member_ref_type (m, false) <<
" > (" << endl;
@@ -5311,7 +5328,7 @@ namespace relational
}
}
- if (call_ != erase_id_call && (call_ != erase_obj_call || smart))
+ if (call_ == load_call)
{
// Call the modifier if we are using a proper one.
//
@@ -5330,16 +5347,16 @@ namespace relational
obj_prefix_, "v", "static_cast<" + db.string () +
"::database&> (db)") << ";";
}
-
- os << "}";
}
+
+ os << "}";
}
protected:
call_type call_;
string obj_prefix_;
string from_;
- member_access* modifier_;
+ member_access* by_value_;
};
//