aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-10-04 11:33:49 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-10-19 11:40:38 +0200
commitb134d7b4f2c105870a98a67ec568c16c9f632aba (patch)
tree03843d3ca794926ff050b5d2bb99d9e3ef0a11ab /odb
parent4eb0df751704345ec8744fe012e64064d5cdb754 (diff)
Initial support for prepared queries
Diffstat (limited to 'odb')
-rw-r--r--odb/header.cxx3
-rw-r--r--odb/options.cli10
-rw-r--r--odb/relational/header.cxx26
-rw-r--r--odb/relational/header.hxx15
-rw-r--r--odb/relational/pgsql/source.cxx5
-rw-r--r--odb/relational/source.cxx363
-rw-r--r--odb/relational/source.hxx24
7 files changed, 309 insertions, 137 deletions
diff --git a/odb/header.cxx b/odb/header.cxx
index 8bf5453..32dc898 100644
--- a/odb/header.cxx
+++ b/odb/header.cxx
@@ -60,6 +60,9 @@ namespace header
if (ctx.options.generate_query ())
{
+ if (!ctx.options.omit_prepared ())
+ os << "#include <odb/prepared-query.hxx>" << endl;
+
os << "#include <odb/result.hxx>" << endl;
if (ctx.features.simple_object)
diff --git a/odb/options.cli b/odb/options.cli
index f61aa0e..ce990b0 100644
--- a/odb/options.cli
+++ b/odb/options.cli
@@ -58,6 +58,16 @@ class options
and can only load objects via their ids."
};
+ bool --omit-prepared
+ {
+ "Omit prepared query execution support code."
+ };
+
+ bool --omit-unprepared
+ {
+ "Omit un-prepared (once-off) query execution support code."
+ };
+
bool --generate-session | -e
{
"Generate session support code. With this option session support will
diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx
index 41b4960..a78697f 100644
--- a/odb/relational/header.cxx
+++ b/odb/relational/header.cxx
@@ -680,13 +680,27 @@ traverse_object (type& c)
//
if (options.generate_query ())
{
- os << "static result<object_type>" << endl
- << "query (database&, const query_base_type&);"
- << endl;
+ if (!options.omit_unprepared ())
+ {
+ os << "static result<object_type>" << endl
+ << "query (database&, const query_base_type&);"
+ << endl;
- os << "static unsigned long long" << endl
- << "erase_query (database&, const query_base_type&);"
- << endl;
+ os << "static unsigned long long" << endl
+ << "erase_query (database&, const query_base_type&);"
+ << endl;
+ }
+
+ if (!options.omit_prepared ())
+ {
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, const query_base_type&);"
+ << endl;
+
+ os << "static odb::details::shared_ptr<result_impl>" << endl
+ << "execute_query (prepared_query_impl&);"
+ << endl;
+ }
}
// create_schema ()
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 9d932ae..fe08a49 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -1124,9 +1124,10 @@ namespace relational
// query ()
//
- os << "static result<view_type>" << endl
- << "query (database&, const query_base_type&);"
- << endl;
+ if (!options.omit_unprepared ())
+ os << "static result<view_type>" << endl
+ << "query (database&, const query_base_type&);"
+ << endl;
view_public_extra_post (c);
@@ -1445,8 +1446,12 @@ namespace relational
generate ()
{
os << "#include <odb/details/buffer.hxx>" << endl
- << "#include <odb/details/unused.hxx>" << endl
- << endl;
+ << "#include <odb/details/unused.hxx>" << endl;
+
+ if (options.generate_query ())
+ os << "#include <odb/details/shared-ptr.hxx>" << endl;
+
+ os << endl;
os << "#include <odb/" << db << "/version.hxx>" << endl
<< "#include <odb/" << db << "/forward.hxx>" << endl
diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx
index da07073..e771053 100644
--- a/odb/relational/pgsql/source.cxx
+++ b/odb/relational/pgsql/source.cxx
@@ -829,9 +829,10 @@ namespace relational
}
virtual void
- post_query_ (type&)
+ post_query_ (type&, bool once_off)
{
- os << "st->deallocate ();";
+ if (once_off)
+ os << "st->deallocate ();";
}
};
entry<class_> class_entry_;
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 8981417..4e407b6 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -2564,92 +2564,227 @@ 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;
+ char const* result_type;
+ if (poly)
+ result_type = "polymorphic_object_result_impl<object_type>";
+ else if (id != 0)
+ result_type = "object_result_impl<object_type>";
+ else
+ result_type = "no_id_object_result_impl<object_type>";
- // Rebind the image if necessary.
+ // Unprepared.
//
- os << "image_type& im (sts.image ());"
- << "binding& imb (sts.select_image_binding (" <<
- (poly_derived ? "depth" : "") << "));"
- << endl;
-
- if (poly_derived)
+ if (!options.omit_unprepared ())
{
- os << "if (imb.version == 0 ||" << endl
- << "check_version (sts.select_image_versions (), im))"
+ // query ()
+ //
+ os << "result< " << traits << "::object_type >" << endl
+ << traits << "::" << endl
+ << "query (database&, const query_base_type& q)"
<< "{"
- << "bind (imb.bind, 0, 0, im, statement_select);"
- << "update_version (sts.select_image_versions ()," << endl
- << "im," << endl
- << "sts.select_image_bindings ());"
+ << "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");
+ 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
+ //
+ os << "unsigned long long " << traits << "::" << endl
+ << "erase_query (database&, const query_base_type& q)"
+ << "{"
+ << "using namespace " << db << ";"
+ << endl
+ << db << "::connection& conn (" << endl
+ << db << "::transaction::current ().connection ());"
+ << endl
+ << "q.init_parameters ();"
+ << "delete_statement st (" << endl;
+ object_erase_query_statement_ctor_args (c, "q");
+ os << ");"
+ << endl
+ << "return st.execute ();"
<< "}";
}
- else
+
+ // Prepared. Very similar to unprepared but has some annoying variations
+ // that make it difficult to factor out something common.
+ //
+ if (!options.omit_prepared ())
{
- os << "if (im.version != sts.select_image_version () ||" << endl
- << "imb.version == 0)"
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const query_base_type& q)"
<< "{"
- << "bind (imb.bind, im, statement_select);"
- << "sts.select_image_version (im.version);"
- << "imb.version++;"
+ << "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);"
+ << "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");
+ os << "));"
+ << endl
+ << "return r;"
<< "}";
- }
- os << "shared_ptr<select_statement> st (" << endl
- << "new (shared) select_statement (" << endl;
- object_query_statement_ctor_args (c);
- os << "));" << endl
- << "st->execute ();";
+ 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 (pq.stmt);"
+ << 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;
- post_query_ (c);
+ // Rebind the image if necessary.
+ //
+ os << "image_type& im (sts.image ());"
+ << "binding& imb (sts.select_image_binding (" <<
+ (poly_derived ? "depth" : "") << "));"
+ << endl;
- char const* result_type;
- if (poly)
- result_type = "polymorphic_object_result_impl<object_type>";
- else if (id != 0)
- result_type = "object_result_impl<object_type>";
- else
- result_type = "no_id_object_result_impl<object_type>";
+ 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 << endl
- << "shared_ptr< odb::" << result_type << " > r (" << endl
- << "new (shared) " << db << "::" << result_type << " (" << endl
- << "q, st, sts));"
- << endl
- << "return result<object_type> (r);"
- << "}";
+ 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));"
+ << "}";
+ }
- // erase_query
- //
- os << "unsigned long long " << traits << "::" << endl
- << "erase_query (database&, const query_base_type& q)"
- << "{"
- << "using namespace " << db << ";"
- << endl
- << db << "::connection& conn (" << endl
- << db << "::transaction::current ().connection ());"
- << endl
- << "delete_statement st (" << endl;
- object_erase_query_statement_ctor_args (c);
- os << ");"
- << endl
- << "return st.execute ();"
- << "}";
}
if (embedded_schema)
@@ -3396,52 +3531,56 @@ traverse_view (type& c)
// query ()
//
- 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
+ << "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 (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);
+ view_query_statement_ctor_args (c);
- os << "));" << endl
- << "st->execute ();";
+ os << "));" << endl
+ << "st->execute ();";
- post_query_ (c);
+ post_query_ (c, true);
- 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);"
- << "}";
+ 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);"
+ << "}";
+ }
}
namespace relational
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 123ac55..4f1a9fc 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -3406,7 +3406,7 @@ namespace relational
//
virtual void
- post_query_ (type&)
+ post_query_ (type&, bool /*once_off*/)
{
}
@@ -3425,20 +3425,20 @@ namespace relational
}
virtual void
- object_query_statement_ctor_args (type&)
+ object_query_statement_ctor_args (type&, std::string const& q)
{
- os << "sts.connection ()," << endl
- << "query_statement + q.clause ()," << endl
- << "q.parameters_binding ()," << endl
+ os << "conn," << endl
+ << "query_statement + " << q << ".clause ()," << endl
+ << q << ".parameters_binding ()," << endl
<< "imb";
}
virtual void
- object_erase_query_statement_ctor_args (type&)
+ object_erase_query_statement_ctor_args (type&, std::string const& q)
{
os << "conn," << endl
- << "erase_query_statement + q.clause ()," << endl
- << "q.parameters_binding ()";
+ << "erase_query_statement + " << q << ".clause ()," << endl
+ << q << ".parameters_binding ()";
}
virtual void
@@ -3456,7 +3456,7 @@ namespace relational
virtual void
view_query_statement_ctor_args (type&)
{
- os << "sts.connection ()," << endl
+ os << "conn," << endl
<< "qs.clause ()," << endl
<< "qs.parameters_binding ()," << endl
<< "imb";
@@ -3663,9 +3663,6 @@ namespace relational
if (embedded_schema)
os << "#include <odb/schema-catalog-impl.hxx>" << endl;
- if (options.generate_query ())
- os << "#include <odb/details/shared-ptr.hxx>" << endl;
-
os << endl;
os << "#include <odb/" << db << "/traits.hxx>" << endl
@@ -3692,6 +3689,9 @@ namespace relational
if (options.generate_query ())
{
+ if (!options.omit_prepared ())
+ os << "#include <odb/" << db << "/prepared-query.hxx>" << endl;
+
if (features.simple_object)
os << "#include <odb/" << db << "/simple-object-result.hxx>" << endl;