summaryrefslogtreecommitdiff
path: root/odb/relational/source.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational/source.cxx')
-rw-r--r--odb/relational/source.cxx474
1 files changed, 358 insertions, 116 deletions
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 5a02703..7516801 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -18,8 +18,8 @@ traverse_object (type& c)
using semantics::data_member;
data_member* id (id_member (c));
- bool auto_id (id ? id->count ("auto") : false);
- bool base_id (id ? &id->scope () != &c : false); // Comes from base.
+ 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);
bool has_ptr (has_a (c, test_pointer));
@@ -49,7 +49,8 @@ traverse_object (type& c)
}
string const& type (class_fq_name (c));
- string traits ("access::object_traits< " + type + " >");
+ string traits ("access::object_traits_impl< " + type + ", id_" +
+ db.string () + " >");
column_count_type const& cc (column_count (c));
os << "// " << class_name (c) << endl
@@ -187,7 +188,7 @@ traverse_object (type& c)
<< "//" << endl
<< "if (--d != 0)"
<< "{"
- << "if (object_traits<base_type>::grow (*i.base, " <<
+ << "if (base_traits::grow (*i.base, " <<
"t + " << cols << "UL" <<
(poly_base != poly_root ? ", d" : "") << "))" << endl
<< "i.base->version++;"
@@ -268,7 +269,7 @@ traverse_object (type& c)
os << "// " << class_name (*poly_base) << " base" << endl
<< "//" << endl
<< "if (sk == statement_select)" << endl
- << "object_traits<base_type>::";
+ << "base_traits::";
if (poly_base == poly_root)
os << "bind (b + n, *i.base, sk);";
@@ -360,7 +361,7 @@ traverse_object (type& c)
os << "// " << class_name (*poly_base) << " base" << endl
<< "//" << endl
<< "if (--d != 0)" << endl
- << "object_traits<base_type>::init (o, *i.base, db" <<
+ << "base_traits::init (o, *i.base, db" <<
(poly_base != poly_root ? ", d" : "") << ");"
<< endl;
}
@@ -450,7 +451,8 @@ traverse_object (type& c)
<< "typeid (" << type << ")," << endl;
if (poly_derived)
- os << "&object_traits< " << class_fq_name (*poly_base) << " >::info";
+ os << "&object_traits_impl< " << class_fq_name (*poly_base) <<
+ ", id_" << db << " >::info";
else
os << "0";
@@ -463,7 +465,7 @@ traverse_object (type& c)
os << "," << endl
<< strlit (string (n, 2, string::npos)) << "," << endl
<< "&odb::create_impl< " << type << " >," << endl
- << "&odb::dispatch_impl< " << type << " >," << endl;
+ << "&odb::dispatch_impl< " << type << ", id_" << db << " >," << endl;
if (poly_derived)
os << "&statements_type::delayed_loader";
@@ -883,7 +885,7 @@ traverse_object (type& c)
// hierarchy.
//
if (poly_derived)
- os << "object_traits<base_type>::persist (db, obj, false, false);"
+ os << "base_traits::persist (db, obj, false, false);"
<< endl;
os << "image_type& im (sts.image ());"
@@ -1135,7 +1137,7 @@ traverse_object (type& c)
//
if (!readonly_base)
{
- os << "object_traits<base_type>::update (db, obj, false, false);"
+ os << "base_traits::update (db, obj, false, false);"
<< endl;
}
else
@@ -1550,7 +1552,7 @@ traverse_object (type& c)
// Call our base last (we erase polymorphic objects from base
// to derived in order not to trigger cascading deletes).
//
- os << "object_traits<base_type>::erase (db, id, false, false);"
+ os << "base_traits::erase (db, id, false, false);"
<< endl;
}
@@ -1787,7 +1789,7 @@ traverse_object (type& c)
// Call our base last (we erase polymorphic objects from base
// to derived in order not to trigger cascading deletes).
//
- os << "object_traits<base_type>::erase (db, obj, false, false);"
+ os << "base_traits::erase (db, obj, false, false);"
<< endl;
}
@@ -2349,7 +2351,7 @@ traverse_object (type& c)
if (poly_derived)
os << "if (--d != 0)" << endl
- << "object_traits<base_type>::load_ (sts.base_statements (), obj" <<
+ << "base_traits::load_ (sts.base_statements (), obj" <<
(poly_base != poly_root ? ", d" : "") << ");"
<< endl;
@@ -2562,60 +2564,6 @@ traverse_object (type& c)
if (options.generate_query ())
{
- // query ()
- //
- os << "result< " << traits << "::object_type >" << endl
- << traits << "::" << endl
- << "query (database&, const query_base_type& q)"
- << "{"
- << "using namespace " << db << ";"
- << "using odb::details::shared;"
- << "using odb::details::shared_ptr;"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << endl
- << "statements_type& sts (" << endl
- << "conn.statement_cache ().find_object<object_type> ());"
- << endl;
-
- // Rebind the image if necessary.
- //
- os << "image_type& im (sts.image ());"
- << "binding& imb (sts.select_image_binding (" <<
- (poly_derived ? "depth" : "") << "));"
- << endl;
-
- if (poly_derived)
- {
- os << "if (imb.version == 0 ||" << endl
- << "check_version (sts.select_image_versions (), im))"
- << "{"
- << "bind (imb.bind, 0, 0, im, statement_select);"
- << "update_version (sts.select_image_versions ()," << endl
- << "im," << endl
- << "sts.select_image_bindings ());"
- << "}";
- }
- else
- {
- os << "if (im.version != sts.select_image_version () ||" << endl
- << "imb.version == 0)"
- << "{"
- << "bind (imb.bind, im, statement_select);"
- << "sts.select_image_version (im.version);"
- << "imb.version++;"
- << "}";
- }
-
- os << "shared_ptr<select_statement> st (" << endl
- << "new (shared) select_statement (" << endl;
- object_query_statement_ctor_args (c);
- os << "));" << endl
- << "st->execute ();";
-
- post_query_ (c);
-
char const* result_type;
if (poly)
result_type = "polymorphic_object_result_impl<object_type>";
@@ -2624,13 +2572,73 @@ traverse_object (type& c)
else
result_type = "no_id_object_result_impl<object_type>";
- os << endl
- << "shared_ptr< odb::" << result_type << " > r (" << endl
- << "new (shared) " << db << "::" << result_type << " (" << endl
- << "q, st, sts));"
- << endl
- << "return result<object_type> (r);"
- << "}";
+ // Unprepared.
+ //
+ if (!options.omit_unprepared ())
+ {
+ // query ()
+ //
+ os << "result< " << traits << "::object_type >" << endl
+ << traits << "::" << endl
+ << "query (database&, const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
+
+ if (poly_derived)
+ {
+ os << "if (imb.version == 0 ||" << endl
+ << "check_version (sts.select_image_versions (), im))"
+ << "{"
+ << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "update_version (sts.select_image_versions ()," << endl
+ << "im," << endl
+ << "sts.select_image_bindings ());"
+ << "}";
+ }
+ else
+ {
+ os << "if (im.version != sts.select_image_version () ||" << endl
+ << "imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+ }
+
+ os << "q.init_parameters ();"
+ << "shared_ptr<select_statement> st (" << endl
+ << "new (shared) select_statement (" << endl;
+ object_query_statement_ctor_args (c, "q", false);
+ os << "));" << endl
+ << "st->execute ();";
+
+ post_query_ (c, true);
+
+ os << endl
+ << "shared_ptr< odb::" << result_type << " > r (" << endl
+ << "new (shared) " << db << "::" << result_type << " (" << endl
+ << "q, st, sts));"
+ << endl
+ << "return result<object_type> (r);"
+ << "}";
+ }
// erase_query
//
@@ -2642,12 +2650,142 @@ traverse_object (type& c)
<< db << "::connection& conn (" << endl
<< db << "::transaction::current ().connection ());"
<< endl
+ << "q.init_parameters ();"
<< "delete_statement st (" << endl;
object_erase_query_statement_ctor_args (c);
os << ");"
<< endl
<< "return st.execute ();"
<< "}";
+
+ // Prepared. Very similar to unprepared but has some annoying variations
+ // that make it difficult to factor out something common.
+ //
+ if (options.generate_prepared ())
+ {
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << "static_cast<" << db << "::connection&> (c));"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
+
+ if (poly_derived)
+ {
+ os << "if (imb.version == 0 ||" << endl
+ << "check_version (sts.select_image_versions (), im))"
+ << "{"
+ << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "update_version (sts.select_image_versions ()," << endl
+ << "im," << endl
+ << "sts.select_image_bindings ());"
+ << "}";
+ }
+ else
+ {
+ os << "if (im.version != sts.select_image_version () ||" << endl
+ << "imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+ }
+
+ os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl
+ << "new (shared) " << db << "::prepared_query_impl (conn));"
+ << "r->name = n;"
+ << "r->execute = &execute_query;"
+ << "r->query = q;"
+ << "r->stmt.reset (" << endl
+ << "new (shared) select_statement (" << endl;
+ object_query_statement_ctor_args (c, "r->query", true);
+ os << "));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "odb::details::shared_ptr<result_impl>" << endl
+ << traits << "::" << endl
+ << "execute_query (prepared_query_impl& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::prepared_query_impl& pq (" << endl
+ << "static_cast<" << db << "::prepared_query_impl&> (q));"
+ << "shared_ptr<select_statement> st (" << endl
+ << "odb::details::inc_ref (" << endl
+ << "static_cast<select_statement*> (pq.stmt.get ())));"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "// The connection used by the current transaction and the" << endl
+ << "// one used to prepare this statement must be the same." << endl
+ << "//" << endl
+ << "assert (&conn == &st->connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_object<object_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
+
+ if (poly_derived)
+ {
+ os << "if (imb.version == 0 ||" << endl
+ << "check_version (sts.select_image_versions (), im))"
+ << "{"
+ << "bind (imb.bind, 0, 0, im, statement_select);"
+ << "update_version (sts.select_image_versions ()," << endl
+ << "im," << endl
+ << "sts.select_image_bindings ());"
+ << "}";
+ }
+ else
+ {
+ os << "if (im.version != sts.select_image_version () ||" << endl
+ << "imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im, statement_select);"
+ << "sts.select_image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+ }
+
+ os << "pq.query.init_parameters ();"
+ << "st->execute ();";
+ post_query_ (c, false);
+
+ os << endl
+ << "return shared_ptr<result_impl> (" << endl
+ << "new (shared) " << db << "::" << result_type << " (" << endl
+ << "pq.query, st, sts));"
+ << "}";
+ }
}
if (embedded_schema)
@@ -2658,7 +2796,8 @@ void relational::source::class_::
traverse_view (type& c)
{
string const& type (class_fq_name (c));
- string traits ("access::view_traits< " + type + " >");
+ string traits ("access::view_traits_impl< " + type + ", id_" +
+ db.string () + " >");
os << "// " << class_name (c) << endl
<< "//" << endl
@@ -3391,54 +3530,157 @@ traverse_view (type& c)
<< "}";
}
- // query ()
+ // Unprepared.
//
- os << "result< " << traits << "::view_type >" << endl
- << traits << "::" << endl
- << "query (database&, const query_base_type& q)"
- << "{"
- << "using namespace " << db << ";"
- << "using odb::details::shared;"
- << "using odb::details::shared_ptr;"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << endl
- << "view_statements< view_type >& sts (" << endl
- << "conn.statement_cache ().find_view<view_type> ());"
- << endl
- << "image_type& im (sts.image ());"
- << "binding& imb (sts.image_binding ());"
- << endl
- << "if (im.version != sts.image_version () || imb.version == 0)"
- << "{"
- << "bind (imb.bind, im);"
- << "sts.image_version (im.version);"
- << "imb.version++;"
- << "}";
+ if (!options.omit_unprepared ())
+ {
+ os << "result< " << traits << "::view_type >" << endl
+ << traits << "::" << endl
+ << "query (database&, const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl
+ << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}";
- if (vq.kind == view_query::runtime)
- os << "const query_base_type& qs (q);";
- else
- os << "const query_base_type& qs (query_statement (q));";
+ if (vq.kind == view_query::runtime)
+ os << "const query_base_type& qs (q);";
+ else
+ os << "const query_base_type& qs (query_statement (q));";
- os << "shared_ptr<select_statement> st (" << endl
- << "new (shared) select_statement (" << endl;
+ os << "qs.init_parameters ();"
+ << "shared_ptr<select_statement> st (" << endl
+ << "new (shared) select_statement (" << endl;
+ view_query_statement_ctor_args (c, "qs", false);
+ os << "));" << endl
+ << "st->execute ();";
- view_query_statement_ctor_args (c);
+ post_query_ (c, true);
- os << "));" << endl
- << "st->execute ();";
+ os << 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);"
+ << "}";
+ }
- post_query_ (c);
+ // Prepared. Very similar to unprepared but has some annoying variations
+ // that make it difficult to factor out something common.
+ //
+ if (options.generate_prepared ())
+ {
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::connection& conn (" << endl
+ << "static_cast<" << db << "::connection&> (c));"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl;
- os << 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);"
- << "}";
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+
+ os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl
+ << "new (shared) " << db << "::prepared_query_impl (conn));"
+ << "r->name = n;"
+ << "r->execute = &execute_query;";
+
+ if (vq.kind == view_query::runtime)
+ os << "r->query = q;";
+ else
+ os << "r->query = query_statement (q);";
+
+ os << "r->stmt.reset (" << endl
+ << "new (shared) select_statement (" << endl;
+ view_query_statement_ctor_args (c, "r->query", true);
+ os << "));"
+ << endl
+ << "return r;"
+ << "}";
+
+ os << "odb::details::shared_ptr<result_impl>" << endl
+ << traits << "::" << endl
+ << "execute_query (prepared_query_impl& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << "using odb::details::shared;"
+ << "using odb::details::shared_ptr;"
+ << endl
+ << db << "::prepared_query_impl& pq (" << endl
+ << "static_cast<" << db << "::prepared_query_impl&> (q));"
+ << "shared_ptr<select_statement> st (" << endl
+ << "odb::details::inc_ref (" << endl
+ << "static_cast<select_statement*> (pq.stmt.get ())));"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "// The connection used by the current transaction and the" << endl
+ << "// one used to prepare this statement must be the same." << endl
+ << "//" << endl
+ << "assert (&conn == &st->connection ());"
+ << endl
+ << "statements_type& sts (" << endl
+ << "conn.statement_cache ().find_view<view_type> ());"
+ << endl;
+
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.image_binding ());"
+ << endl
+ << "if (im.version != sts.image_version () || imb.version == 0)"
+ << "{"
+ << "bind (imb.bind, im);"
+ << "sts.image_version (im.version);"
+ << "imb.version++;"
+ << "}";
+
+ os << "pq.query.init_parameters ();"
+ << "st->execute ();";
+
+ post_query_ (c, false);
+
+ os << endl
+ << "return shared_ptr<result_impl> (" << endl
+ << "new (shared) " << db << "::view_result_impl<view_type> (" << endl
+ << "pq.query, st, sts));"
+ << "}";
+ }
}
namespace relational