summaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-10-27 15:16:49 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-10-27 15:16:49 +0200
commit8d82c02a90cd7cc3f161828624db5b973585c34c (patch)
tree7b04f0b5e1b9e6eb3a2e76395df6a132be7a78d0 /odb/relational
parent9d10c570acf1b7e8ed7c0a750ae3edfa70da200b (diff)
Add support for persistent classes without object ids
New pragma id (object). New test: common/no-id.
Diffstat (limited to 'odb/relational')
-rw-r--r--odb/relational/header.hxx119
-rw-r--r--odb/relational/inline.hxx34
-rw-r--r--odb/relational/oracle/source.cxx2
-rw-r--r--odb/relational/pgsql/source.cxx34
-rw-r--r--odb/relational/processor.cxx19
-rw-r--r--odb/relational/source.hxx372
6 files changed, 326 insertions, 254 deletions
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 7c74d09..a331b3f 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -925,6 +925,7 @@ namespace relational
virtual void
traverse_object (type& c)
{
+ bool abstract (context::abstract (c));
string const& type (c.fq_name ());
semantics::data_member* id (id_member (c));
@@ -1013,6 +1014,15 @@ namespace relational
<< "};";
}
}
+ else if (!abstract)
+ {
+ // Object without id.
+ //
+ os << "typedef void id_type;"
+ << endl
+ << "static const bool auto_id = false;"
+ << endl;
+ }
// image_type
//
@@ -1033,17 +1043,19 @@ namespace relational
// id ()
//
- if (id != 0)
- {
+ if (id != 0 || !abstract)
+ // We want to generate a dummy void id() accessor even if this
+ // object has no id to help us in the runtime. This way we can
+ // generic code that will both for both void and non-void ids.
+ //
os << "static id_type" << endl
<< "id (const object_type&);"
<< endl;
- if (options.generate_query ())
- os << "static id_type" << endl
- << "id (const image_type&);"
- << endl;
- }
+ if (id != 0 && options.generate_query ())
+ os << "static id_type" << endl
+ << "id (const image_type&);"
+ << endl;
// grow ()
//
@@ -1095,7 +1107,7 @@ namespace relational
//
// The rest only applies to concrete objects.
//
- if (abstract (c))
+ if (abstract)
{
object_public_extra_post (c);
os << "};";
@@ -1124,8 +1136,9 @@ namespace relational
// Statement cache (forward declaration).
//
- os << "struct container_statement_cache_type;"
- << endl;
+ if (id != 0)
+ os << "struct container_statement_cache_type;"
+ << endl;
// column_count
//
@@ -1139,13 +1152,17 @@ namespace relational
// Statements.
//
- os << "static const char persist_statement[];"
- << "static const char find_statement[];";
+ os << "static const char persist_statement[];";
- if (cc.total != cc.id + cc.inverse + cc.readonly)
- os << "static const char update_statement[];";
+ if (id != 0)
+ {
+ os << "static const char find_statement[];";
- os << "static const char erase_statement[];";
+ if (cc.total != cc.id + cc.inverse + cc.readonly)
+ os << "static const char update_statement[];";
+
+ os << "static const char erase_statement[];";
+ }
if (options.generate_query ())
{
@@ -1178,29 +1195,32 @@ namespace relational
"object_type&);"
<< endl;
- // update ()
- //
- if (!readonly (c))
- os << "static void" << endl
- << "update (database&, const object_type&);"
+ if (id != 0)
+ {
+ // find ()
+ //
+ if (c.default_ctor ())
+ os << "static pointer_type" << endl
+ << "find (database&, const id_type&);"
+ << endl;
+
+ os << "static bool" << endl
+ << "find (database&, const id_type&, object_type&);"
<< endl;
- // erase ()
- //
- os << "static void" << endl
- << "erase (database&, const id_type&);"
- << endl;
+ // update ()
+ //
+ if (!readonly (c))
+ os << "static void" << endl
+ << "update (database&, const object_type&);"
+ << endl;
- // find ()
- //
- if (c.default_ctor ())
- os << "static pointer_type" << endl
- << "find (database&, const id_type&);"
+ // erase ()
+ //
+ os << "static void" << endl
+ << "erase (database&, const id_type&);"
<< endl;
-
- os << "static bool" << endl
- << "find (database&, const id_type&, object_type&);"
- << endl;
+ }
// query ()
//
@@ -1230,21 +1250,24 @@ namespace relational
//
os << "public:" << endl;
- // Load the object image.
- //
- os << "static bool" << endl
- << "find_ (" << db << "::object_statements< object_type >&, " <<
- "const id_type&);"
- << endl;
+ if (id != 0)
+ {
+ // Load the object image.
+ //
+ os << "static bool" << endl
+ << "find_ (" << db << "::object_statements< object_type >&, " <<
+ "const id_type&);"
+ << endl;
- // Load the rest of the object (containers, etc). Expects the id
- // image in the object statements to be initialized to the object
- // id.
- //
- os << "static void" << endl
- << "load_ (" << db << "::object_statements< object_type >&, " <<
- "object_type&);"
- << endl;
+ // Load the rest of the object (containers, etc). Expects the id
+ // image in the object statements to be initialized to the object
+ // id.
+ //
+ os << "static void" << endl
+ << "load_ (" << db << "::object_statements< object_type >&, " <<
+ "object_type&);"
+ << endl;
+ }
os << "};";
}
diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx
index 78d81bf..3968dce 100644
--- a/odb/relational/inline.hxx
+++ b/odb/relational/inline.hxx
@@ -102,7 +102,7 @@ namespace relational
virtual void
traverse_object (type& c)
{
- bool abst (abstract (c));
+ bool abstract (context::abstract (c));
string const& type (c.fq_name ());
string traits ("access::object_traits< " + type + " >");
@@ -115,28 +115,34 @@ namespace relational
object_extra (c);
- if (id != 0)
+ // id (object_type)
+ //
+ if (id != 0 || !abstract)
{
- // id (object_type)
- //
os << "inline" << endl
<< traits << "::id_type" << endl
<< traits << "::" << endl
- << "id (const object_type& obj)"
+ << "id (const object_type&" << (id != 0 ? " obj" : "") << ")"
<< "{";
- if (base_id)
- os << "return object_traits< " << id->scope ().fq_name () <<
- " >::id (obj);";
- else
- os << "return obj." << id->name () << ";";
+ if (id != 0)
+ {
+ if (base_id)
+ os << "return object_traits< " << id->scope ().fq_name () <<
+ " >::id (obj);";
+ else
+ os << "return obj." << id->name () << ";";
+ }
os << "}";
+ }
- // id (image_type)
- //
+ if (id != 0)
+ {
if (options.generate_query () && base_id)
{
+ // id (image_type)
+ //
os << "inline" << endl
<< traits << "::id_type" << endl
<< traits << "::" << endl
@@ -175,7 +181,7 @@ namespace relational
//
// The rest only applies to concrete objects.
//
- if (abst)
+ if (abstract)
return;
// callback ()
@@ -244,7 +250,7 @@ namespace relational
// load_()
//
- if (!has_a (c, test_container))
+ if (id != 0 && !has_a (c, test_container))
{
os << "inline" << endl
<< "void " << traits << "::" << endl
diff --git a/odb/relational/oracle/source.cxx b/odb/relational/oracle/source.cxx
index 880b496..a22c235 100644
--- a/odb/relational/oracle/source.cxx
+++ b/odb/relational/oracle/source.cxx
@@ -876,7 +876,7 @@ namespace relational
{
semantics::data_member* id (id_member (c));
- if (id->count ("auto"))
+ if (id != 0 && id->count ("auto"))
{
os << endl
<< strlit (" RETURNING " +
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index c45b40e..c17edc6 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -988,6 +988,7 @@ namespace relational
if (abstract (c))
return;
+ semantics::data_member* id (id_member (c));
column_count_type const& cc (column_count (c));
string const& n (c.fq_name ());
@@ -998,20 +999,24 @@ namespace relational
os << name_decl << endl
<< "persist_statement_name[] = " << strlit (fn + "_persist") <<
";"
- << endl
- << name_decl << endl
- << "find_statement_name[] = " << strlit (fn + "_find") << ";"
<< endl;
- if (cc.total != cc.id + cc.inverse + cc.readonly)
+ if (id != 0)
+ {
os << name_decl << endl
- << "update_statement_name[] = " << strlit (fn + "_update") <<
- ";"
+ << "find_statement_name[] = " << strlit (fn + "_find") << ";"
<< endl;
- os << name_decl << endl
- << "erase_statement_name[] = " << strlit (fn + "_erase") << ";"
- << endl;
+ if (cc.total != cc.id + cc.inverse + cc.readonly)
+ os << name_decl << endl
+ << "update_statement_name[] = " << strlit (fn + "_update") <<
+ ";"
+ << endl;
+
+ os << name_decl << endl
+ << "erase_statement_name[] = " << strlit (fn + "_erase") << ";"
+ << endl;
+ }
// Query statement name.
//
@@ -1029,7 +1034,6 @@ namespace relational
// Statement types.
//
string oid_decl ("const unsigned int " + traits);
- semantics::data_member* id_m (id_member (c));
// persist_statement_types.
//
@@ -1046,20 +1050,21 @@ namespace relational
// find_statement_types.
//
+ if (id != 0)
{
os << oid_decl << endl
<< "find_statement_types[] ="
<< "{";
instance<statement_oids> st (statement_select);
- st->traverse_column (*id_m, "", true);
+ st->traverse_column (*id, "", true);
os << "};";
}
// update_statement_types.
//
- if (cc.total != cc.id + cc.inverse + cc.readonly)
+ if (id != 0 && cc.total != cc.id + cc.inverse + cc.readonly)
{
os << oid_decl << endl
<< "update_statement_types[] ="
@@ -1072,7 +1077,7 @@ namespace relational
{
instance<statement_oids> st (statement_where);
- st->traverse_column (*id_m, "", false);
+ st->traverse_column (*id, "", false);
}
os << "};";
@@ -1080,13 +1085,14 @@ namespace relational
// erase_statement_types.
//
+ if (id != 0)
{
os << oid_decl << endl
<< "erase_statement_types[] ="
<< "{";
instance<statement_oids> st (statement_where);
- st->traverse_column (*id_m, "", true);
+ st->traverse_column (*id, "", true);
os << "};";
}
diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx
index fdddf9a..d0587ca 100644
--- a/odb/relational/processor.cxx
+++ b/odb/relational/processor.cxx
@@ -851,6 +851,20 @@ namespace relational
throw operation_failed ();
}
+ // Make sure the pointed-to class has object id.
+ //
+ if (context::id_member (*c) == 0)
+ {
+ os << m.file () << ":" << m.line () << ":" << m.column () << ": "
+ << "error: pointed-to class '" << c->fq_name () << "' "
+ << "has no object id" << endl;
+
+ os << c->file () << ":" << c->line () << ":" << c->column () << ": "
+ << "info: class '" << c->name () << "' is defined here" << endl;
+
+ throw operation_failed ();
+ }
+
// See if this is the inverse side of a bidirectional relationship.
// If so, then resolve the member and cache it in the context.
//
@@ -882,8 +896,9 @@ namespace relational
}
// @@ Would be good to check that the other end is actually
- // an object pointer and is not marked as inverse. But the
- // other class may not have been processed yet.
+ // an object pointer, is not marked as inverse, and points
+ // to the correct object. But the other class may not have
+ // been processed yet.
//
m.remove ("inverse");
m.set (kp + (kp.empty () ? "": "-") + "inverse", im);
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 9b04ae4..a82fe6a 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -2251,7 +2251,7 @@ namespace relational
virtual void
traverse_object (type& c)
{
- bool abst (abstract (c));
+ bool abstract (context::abstract (c));
string const& type (c.fq_name ());
string traits ("access::object_traits< " + type + " >");
@@ -2461,7 +2461,7 @@ namespace relational
//
// The rest only applies to concrete objects.
//
- if (abst)
+ if (abstract)
return;
//
@@ -2470,6 +2470,7 @@ namespace relational
// Statement cache (definition).
//
+ if (id != 0)
{
os << "struct " << traits << "::container_statement_cache_type"
<< "{";
@@ -2494,7 +2495,6 @@ namespace relational
//
string const& table (table_qname (c));
- string const& id_col (column_qname (*id));
// persist_statement
//
@@ -2519,52 +2519,57 @@ namespace relational
<< endl;
}
- // find_statement
- //
+ if (id != 0)
{
- os << "const char " << traits << "::find_statement[] =" << endl
- << strlit ("SELECT ") << endl;
+ string const& id_col (column_qname (*id));
- instance<object_columns> t (table, statement_select);
- t->traverse (c);
+ // find_statement
+ //
+ {
+ os << "const char " << traits << "::find_statement[] =" << endl
+ << strlit ("SELECT ") << endl;
- os << strlit (" FROM " + table) << endl;
+ instance<object_columns> t (table, statement_select);
+ t->traverse (c);
- bool f (false);
- instance<object_joins> j (c, f); // @@ (im)perfect forwarding
- j->traverse (c);
- j->write ();
+ os << strlit (" FROM " + table) << endl;
- instance<query_parameters> qp;
- os << strlit (" WHERE " + table + "." + id_col + "=" +
- qp->next ()) << ";"
- << endl;
- }
+ bool f (false);
+ instance<object_joins> j (c, f); // @@ (im)perfect forwarding
+ j->traverse (c);
+ j->write ();
- // update_statement
- //
- if (cc.total != cc.id + cc.inverse + cc.readonly)
- {
- os << "const char " << traits << "::update_statement[] " <<
- "=" << endl
- << strlit ("UPDATE " + table + " SET ") << endl;
+ instance<query_parameters> qp;
+ os << strlit (" WHERE " + table + "." + id_col + "=" +
+ qp->next ()) << ";"
+ << endl;
+ }
- instance<query_parameters> qp;
- instance<object_columns> t (statement_update, true, qp.get ());
- t->traverse (c);
+ // update_statement
+ //
+ if (cc.total != cc.id + cc.inverse + cc.readonly)
+ {
+ os << "const char " << traits << "::update_statement[] " <<
+ "=" << endl
+ << strlit ("UPDATE " + table + " SET ") << endl;
- os << strlit (" WHERE " + id_col + "=" + qp->next ()) << ";"
- << endl;
- }
+ instance<query_parameters> qp;
+ instance<object_columns> t (statement_update, true, qp.get ());
+ t->traverse (c);
- // erase_statement
- //
- {
- instance<query_parameters> qp;
- os << "const char " << traits << "::erase_statement[] =" << endl
- << strlit ("DELETE FROM " + table) << endl
- << strlit (" WHERE " + id_col + "=" + qp->next ()) << ";"
- << endl;
+ os << strlit (" WHERE " + id_col + "=" + qp->next ()) << ";"
+ << endl;
+ }
+
+ // erase_statement
+ //
+ {
+ instance<query_parameters> qp;
+ os << "const char " << traits << "::erase_statement[] =" << endl
+ << strlit ("DELETE FROM " + table) << endl
+ << strlit (" WHERE " + id_col + "=" + qp->next ()) << ";"
+ << endl;
+ }
}
if (options.generate_query ())
@@ -2613,6 +2618,11 @@ namespace relational
// persist ()
//
+ char const* object_statements_type (
+ id != 0
+ ? "object_statements< object_type >"
+ : "object_statements_no_id< object_type >");
+
os << "void " << traits << "::" << endl
<< "persist (database&, " << (auto_id ? "" : "const ") <<
"object_type& obj)"
@@ -2621,7 +2631,7 @@ namespace relational
<< endl
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
- << "object_statements< object_type >& sts (" << endl
+ << object_statements_type << "& sts (" << endl
<< "conn.statement_cache ().find_object<object_type> ());"
<< "image_type& im (sts.image ());"
<< "binding& imb (sts.insert_image_binding ());"
@@ -2684,7 +2694,7 @@ namespace relational
// update ()
//
- if (!readonly (c))
+ if (id != 0 && !readonly (c))
{
os << "void " << traits << "::" << endl
<< "update (database&, const object_type& obj)"
@@ -2693,7 +2703,7 @@ namespace relational
<< endl
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
- << "object_statements< object_type >& sts (" << endl
+ << object_statements_type << "& sts (" << endl
<< "conn.statement_cache ().find_object<object_type> ());"
<< endl;
@@ -2756,51 +2766,54 @@ namespace relational
// erase ()
//
- os << "void " << traits << "::" << endl
- << "erase (database&, const id_type& id)"
- << "{"
- << "using namespace " << db << ";"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find_object<object_type> ());"
- << endl;
+ if (id != 0)
+ {
+ os << "void " << traits << "::" << endl
+ << "erase (database&, const id_type& id)"
+ << "{"
+ << "using namespace " << db << ";"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << object_statements_type << "& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
- // Initialize id image.
- //
- os << "id_image_type& i (sts.id_image ());"
- << "init (i, id);"
- << endl;
+ // Initialize id image.
+ //
+ os << "id_image_type& i (sts.id_image ());"
+ << "init (i, id);"
+ << endl;
- os << "binding& idb (sts.id_image_binding ());"
- << "if (i.version != sts.id_image_version () || idb.version == 0)"
- << "{"
- << "bind (idb.bind, i);"
- << "sts.id_image_version (i.version);"
- << "idb.version++;"
- << "}";
+ os << "binding& idb (sts.id_image_binding ());"
+ << "if (i.version != sts.id_image_version () || idb.version == 0)"
+ << "{"
+ << "bind (idb.bind, i);"
+ << "sts.id_image_version (i.version);"
+ << "idb.version++;"
+ << "}";
- // Erase containers first so that there are no reference
- // violations (we don't want to reply on ON DELETE CASCADE
- // here since in case of a custom schema, it might not be
- // there).
- //
- if (straight_containers)
- {
- instance<container_calls> t (container_calls::erase_call);
- t->traverse (c);
- os << endl;
- }
+ // Erase containers first so that there are no reference
+ // violations (we don't want to reply on ON DELETE CASCADE
+ // here since in case of a custom schema, it might not be
+ // there).
+ //
+ if (straight_containers)
+ {
+ instance<container_calls> t (container_calls::erase_call);
+ t->traverse (c);
+ os << endl;
+ }
- os << "if (sts.erase_statement ().execute () != 1)" << endl
- << "throw object_not_persistent ();";
+ os << "if (sts.erase_statement ().execute () != 1)" << endl
+ << "throw object_not_persistent ();";
- os << "}";
+ os << "}";
+ }
- // find ()
+ // find (id)
//
- if (c.default_ctor ())
+ if (id != 0 && c.default_ctor ())
{
os << traits << "::pointer_type" << endl
<< traits << "::" << endl
@@ -2810,9 +2823,9 @@ namespace relational
<< endl
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
- << "object_statements< object_type >& sts (" << endl
+ << object_statements_type << "& sts (" << endl
<< "conn.statement_cache ().find_object<object_type> ());"
- << "object_statements< object_type >::auto_lock l (sts);"
+ << object_statements_type << "::auto_lock l (sts);"
<< endl
<< "if (l.locked ())"
<< "{"
@@ -2848,110 +2861,118 @@ namespace relational
<< "}";
}
- os << "bool " << traits << "::" << endl
- << "find (database& db, const id_type& id, object_type& obj)"
- << "{"
- << "using namespace " << db << ";"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << "object_statements< object_type >& sts (" << endl
- << "conn.statement_cache ().find_object<object_type> ());"
- << "object_statements< object_type >::auto_lock l (sts);"
- << endl
- << "if (l.locked ())"
- << "{"
- << "if (!find_ (sts, id))" << endl
- << "return false;"
- << "}"
- << "reference_cache_traits< object_type >::insert_guard ig (" << endl
- << "reference_cache_traits< object_type >::insert (db, id, obj));"
- << endl
- << "if (l.locked ())"
- << "{"
- << "callback (db, obj, callback_event::pre_load);"
- << "init (obj, sts.image (), db);";
-
- init_value_extra ();
+ // find (id, obj)
+ //
+ if (id != 0)
+ {
+ os << "bool " << traits << "::" << endl
+ << "find (database& db, const id_type& id, object_type& obj)"
+ << "{"
+ << "using namespace " << db << ";"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << object_statements_type << "& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << object_statements_type << "::auto_lock l (sts);"
+ << endl
+ << "if (l.locked ())"
+ << "{"
+ << "if (!find_ (sts, id))" << endl
+ << "return false;"
+ << "}"
+ << "reference_cache_traits< object_type >::insert_guard ig (" << endl
+ << "reference_cache_traits< object_type >::insert (db, id, obj));"
+ << endl
+ << "if (l.locked ())"
+ << "{"
+ << "callback (db, obj, callback_event::pre_load);"
+ << "init (obj, sts.image (), db);";
- os << "load_ (sts, obj);"
- << "sts.load_delayed ();"
- << "l.unlock ();"
- << "callback (db, obj, callback_event::post_load);"
- << "}"
- << "else" << endl
- << "sts.delay_load (id, obj, ig.position ());"
- << endl;
+ init_value_extra ();
- os << "ig.release ();"
- << "return true;"
- << "}";
+ os << "load_ (sts, obj);"
+ << "sts.load_delayed ();"
+ << "l.unlock ();"
+ << "callback (db, obj, callback_event::post_load);"
+ << "}"
+ << "else" << endl
+ << "sts.delay_load (id, obj, ig.position ());"
+ << endl;
- //
- //
- os << "bool " << traits << "::" << endl
- << "find_ (" << db << "::object_statements< object_type >& sts, " <<
- "const id_type& id)"
- << "{"
- << "using namespace " << db << ";"
- << endl;
+ os << "ig.release ();"
+ << "return true;"
+ << "}";
+ }
- // Initialize id image.
+ // find_ ()
//
- os << "id_image_type& i (sts.id_image ());"
- << "init (i, id);"
- << endl;
-
- os << "binding& idb (sts.id_image_binding ());"
- << "if (i.version != sts.id_image_version () || idb.version == 0)"
- << "{"
- << "bind (idb.bind, i);"
- << "sts.id_image_version (i.version);"
- << "idb.version++;"
- << "}";
+ if (id != 0)
+ {
+ os << "bool " << traits << "::" << endl
+ << "find_ (" << db << "::" << object_statements_type << "& " <<
+ "sts, const id_type& id)"
+ << "{"
+ << "using namespace " << db << ";"
+ << endl;
- // Rebind data image.
- //
- os << "image_type& im (sts.image ());"
- << "binding& imb (sts.select_image_binding ());"
- << endl
- << "if (im.version != sts.select_image_version () || " <<
- "imb.version == 0)"
- << "{"
- << "bind (imb.bind, im, statement_select);"
- << "sts.select_image_version (im.version);"
- << "imb.version++;"
- << "}"
- << "select_statement& st (sts.find_statement ());"
- << "st.execute ();"
- << "select_statement::result r (st.fetch ());";
+ // Initialize id image.
+ //
+ os << "id_image_type& i (sts.id_image ());"
+ << "init (i, id);"
+ << endl;
- if (grow)
- os << endl
- << "if (r == select_statement::truncated)"
+ os << "binding& idb (sts.id_image_binding ());"
+ << "if (i.version != sts.id_image_version () || idb.version == 0)"
<< "{"
- << "if (grow (im, sts.select_image_truncated ()))" << endl
- << "im.version++;"
+ << "bind (idb.bind, i);"
+ << "sts.id_image_version (i.version);"
+ << "idb.version++;"
+ << "}";
+
+ // Rebind data image.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding ());"
<< endl
- << "if (im.version != sts.select_image_version ())"
+ << "if (im.version != sts.select_image_version () || " <<
+ "imb.version == 0)"
<< "{"
<< "bind (imb.bind, im, statement_select);"
<< "sts.select_image_version (im.version);"
<< "imb.version++;"
- << "st.refetch ();"
<< "}"
- << "}";
+ << "select_statement& st (sts.find_statement ());"
+ << "st.execute ();"
+ << "select_statement::result r (st.fetch ());";
- os << "st.free_result ();"
- << "return r != select_statement::no_data;"
- << "}";
+ if (grow)
+ os << endl
+ << "if (r == select_statement::truncated)"
+ << "{"
+ << "if (grow (im, sts.select_image_truncated ()))" << endl
+ << "im.version++;"
+ << endl
+ << "if (im.version != sts.select_image_version ())"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "st.refetch ();"
+ << "}"
+ << "}";
+
+ os << "st.free_result ();"
+ << "return r != select_statement::no_data;"
+ << "}";
+ }
// load_()
//
if (containers)
{
os << "void " << traits << "::" << endl
- << "load_ (" << db << "::object_statements< object_type >& " <<
+ << "load_ (" << db << "::" << object_statements_type << "& " <<
"sts, object_type& obj)"
<< "{"
<< db << "::binding& idb (sts.id_image_binding ());"
@@ -2976,7 +2997,7 @@ namespace relational
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
<< endl
- << "object_statements< object_type >& sts (" << endl
+ << object_statements_type << "& sts (" << endl
<< "conn.statement_cache ().find_object<object_type> ());"
<< endl
<< "image_type& im (sts.image ());"
@@ -2999,11 +3020,14 @@ namespace relational
post_query_ (c);
+ char const* result_type (
+ id != 0
+ ? "object_result_impl<object_type>"
+ : "object_result_impl_no_id<object_type>");
+
os << endl
- << "shared_ptr<odb::result_impl<object_type, " <<
- "class_object> > r (" << endl
- << "new (shared) " << db <<
- "::result_impl<object_type, class_object> (" << endl
+ << "shared_ptr< odb::" << result_type << " > r (" << endl
+ << "new (shared) " << db << "::" << result_type << " (" << endl
<< "q, st, sts));"
<< endl
<< "return result<object_type> (r);"
@@ -3928,10 +3952,8 @@ namespace relational
post_query_ (c);
os << endl
- << "shared_ptr<odb::result_impl<view_type, " <<
- "class_view> > r (" << endl
- << "new (shared) " << db <<
- "::result_impl<view_type, class_view> (" << endl
+ << "shared_ptr< odb::view_result_impl<view_type> > r (" << endl
+ << "new (shared) " << db << "::view_result_impl<view_type> (" << endl
<< "qs, st, sts));"
<< endl
<< "return result<view_type> (r);"