aboutsummaryrefslogtreecommitdiff
path: root/common/prepared
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-10-12 17:24:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-10-19 11:41:11 +0200
commitf2e4c2c70344dd1a98593cfbe9256d1b3ed54f27 (patch)
tree713e2b8625aa9db41f2c18194baf68b830df39a3 /common/prepared
parent3fd1098c70a36cdffa256b6d9fd721cf95c6f482 (diff)
Completion of prepared query support
Diffstat (limited to 'common/prepared')
-rw-r--r--common/prepared/driver.cxx276
-rw-r--r--common/prepared/makefile2
-rw-r--r--common/prepared/test.hxx7
3 files changed, 281 insertions, 4 deletions
diff --git a/common/prepared/driver.cxx b/common/prepared/driver.cxx
index 24a3788..6738e6b 100644
--- a/common/prepared/driver.cxx
+++ b/common/prepared/driver.cxx
@@ -5,7 +5,8 @@
// Test prepared query functionality.
//
-#include <memory> // std::auto_ptr
+#include <memory> // std::auto_ptr, std::unique_ptr
+#include <utility> // std::move
#include <cassert>
#include <iostream>
@@ -13,6 +14,7 @@
#include <odb/transaction.hxx>
#include <common/common.hxx>
+#include <common/config.hxx> // HAVE_CXX11
#include "test.hxx"
#include "test-odb.hxx"
@@ -20,6 +22,26 @@
using namespace std;
using namespace odb::core;
+struct params
+{
+ unsigned short age;
+ std::string name;
+};
+
+static void
+query_factory (const char* name, connection& c)
+{
+ typedef odb::query<person> query;
+
+ auto_ptr<params> p (new params);
+ prepared_query<person> pq (
+ c.prepare_query<person> (
+ name,
+ query::age > query::_ref (p->age) &&
+ query::name != query::_ref (p->name)));
+ c.cache_query (pq, p);
+}
+
int
main (int argc, char* argv[])
{
@@ -47,14 +69,14 @@ main (int argc, char* argv[])
typedef odb::prepared_query<person> prep_query;
typedef odb::result<person> result;
- // Simple case: uncached query.
+ // Uncached query.
//
{
transaction t (db->begin ());
unsigned short age (90);
prep_query pq (
- t.connection ().prepare_query<person> (
+ db->prepare_query<person> (
"person-age-query",
query::age > query::_ref (age)));
@@ -64,6 +86,254 @@ main (int argc, char* argv[])
assert (size (r) == i);
}
+ age = 90;
+ result r (pq.execute ());
+ result::iterator i (r.begin ());
+ assert (i != r.end () && i->name_ == "John First" && i->age_ == 91);
+ assert (++i == r.end ());
+
+ t.commit ();
+ }
+
+ // Cached query without parameters.
+ //
+ {
+ for (unsigned short i (1); i < 6; ++i)
+ {
+ transaction t (db->begin ());
+
+ prep_query pq (db->lookup_query<person> ("person-val-age-query"));
+
+ if (!pq)
+ {
+ assert (i == 1);
+ pq = db->prepare_query<person> (
+ "person-val-age-query",
+ query::age > 90);
+ db->cache_query (pq);
+ prep_query pq1 (db->lookup_query<person> ("person-val-age-query"));
+ }
+ else if (i == 2)
+ {
+ try
+ {
+ db->cache_query (pq);
+ assert (false);
+ }
+ catch (const odb::prepared_already_cached&)
+ {
+ }
+ }
+
+ result r (pq.execute ());
+ assert (size (r) == 1);
+
+ t.commit ();
+ }
+ }
+
+ // Cached query with parameters.
+ //
+ {
+ for (unsigned short i (1); i < 6; ++i)
+ {
+ transaction t (db->begin ());
+
+ unsigned short* age;
+ prep_query pq (db->lookup_query<person> ("person-ref-age-query", age));
+
+ if (!pq)
+ {
+ assert (i == 1);
+
+#ifdef HAVE_CXX11
+ unique_ptr<unsigned short> p (new unsigned short);
+#else
+ auto_ptr<unsigned short> p (new unsigned short);
+#endif
+ age = p.get ();
+ pq = db->prepare_query<person> (
+ "person-ref-age-query",
+ query::age > query::_ref (*age));
+
+#ifdef HAVE_CXX11
+ db->cache_query (pq, move (p));
+#else
+ db->cache_query (pq, p);
+#endif
+ }
+ else if (i == 2)
+ {
+ // Object type mismatch.
+ //
+ try
+ {
+ db->lookup_query<int> ("person-ref-age-query", age);
+ assert (false);
+ }
+ catch (const odb::prepared_type_mismatch&)
+ {
+ }
+
+ // Parameters type mismatch.
+ //
+ try
+ {
+ int* age;
+ db->lookup_query<person> ("person-ref-age-query", age);
+ assert (false);
+ }
+ catch (const odb::prepared_type_mismatch&)
+ {
+ }
+ }
+
+ *age = 100 - i * 10;
+ result r (pq.execute ());
+ assert (size (r) == i);
+
+ t.commit ();
+ }
+ }
+
+ // Cached query with factory.
+ //
+ {
+ db->query_factory ("person-params-query", &query_factory);
+
+ for (unsigned int i (1); i < 6; ++i)
+ {
+ transaction t (db->begin ());
+
+ params* p;
+ prep_query pq (db->lookup_query<person> ("person-params-query", p));
+ assert (pq);
+
+ p->age = 100 - i * 10;
+ p->name = "John First";
+ result r (pq.execute ());
+ assert (size (r) == i - 1);
+
+ t.commit ();
+ }
+
+ db->query_factory ("person-params-query", 0);
+ }
+
+ // Cached query with wildcard factory.
+ //
+ {
+ db->query_factory ("", &query_factory);
+
+ for (unsigned int i (1); i < 6; ++i)
+ {
+ transaction t (db->begin ());
+
+ params* p;
+ prep_query pq (db->lookup_query<person> ("person-params-query-1", p));
+ assert (pq);
+
+ p->age = 100 - i * 10;
+ p->name = "John First";
+ result r (pq.execute ());
+ assert (size (r) == i - 1);
+
+ t.commit ();
+ }
+
+ db->query_factory ("", 0);
+ }
+
+ // Cached query with lambda factory.
+ //
+#ifdef HAVE_CXX11
+ {
+ db->query_factory (
+ "person-params-query-2",
+ [] (const char* name, connection& c)
+ {
+ auto_ptr<params> p (new params);
+ prepared_query<person> pq (
+ c.prepare_query<person> (
+ name,
+ query::age > query::_ref (p->age) &&
+ query::name != query::_ref (p->name)));
+ c.cache_query (pq, p);
+ });
+
+ for (unsigned int i (1); i < 6; ++i)
+ {
+ transaction t (db->begin ());
+
+ params* p;
+ prep_query pq (db->lookup_query<person> ("person-params-query-2", p));
+ assert (pq);
+
+ p->age = 100 - i * 10;
+ p->name = "John First";
+ result r (pq.execute ());
+ assert (size (r) == i - 1);
+
+ t.commit ();
+ }
+
+ db->query_factory ("person-params-query-2", 0);
+ }
+#endif
+
+ // View prepared query.
+ //
+ {
+ typedef odb::query<person_view> query;
+ typedef odb::prepared_query<person_view> prep_query;
+ typedef odb::result<person_view> result;
+
+ transaction t (db->begin ());
+
+ unsigned short age (90);
+ prep_query pq (
+ db->prepare_query<person_view> (
+ "person-view-age-query",
+ query::age > query::_ref (age)));
+
+ for (unsigned short i (1); i < 6; ++i, age -= 10)
+ {
+ result r (pq.execute ());
+ assert (size (r) == i);
+ }
+
+ age = 90;
+ result r (pq.execute ());
+ result::iterator i (r.begin ());
+ assert (i != r.end () && i->name == "John First" && i->age == 91);
+ assert (++i == r.end ());
+
+ t.commit ();
+ }
+
+ // By-ref parameter image growth.
+ //
+ {
+ transaction t (db->begin ());
+
+ string name;
+ prep_query pq (
+ db->prepare_query<person> (
+ "person-name-query",
+ query::name != query::_ref (name)));
+
+ {
+ name = "John First";
+ result r (pq.execute ());
+ assert (size (r) == 4);
+ }
+
+ {
+ name.assign (2048, 'x');
+ result r (pq.execute ());
+ assert (size (r) == 5);
+ }
+
t.commit ();
}
}
diff --git a/common/prepared/makefile b/common/prepared/makefile
index 6da88d3..4126b54 100644
--- a/common/prepared/makefile
+++ b/common/prepared/makefile
@@ -35,7 +35,7 @@ gen := $(addprefix $(out_base)/,$(genf))
$(gen): $(odb)
$(gen): odb := $(odb)
$(gen) $(dist): export odb_options += --database $(db_id) --generate-schema \
---generate-query --omit-unprepared --table-prefix prepared_
+--generate-query --generate-prepared --omit-unprepared --table-prefix prepared_
$(gen): cpp_options := -I$(src_base)
$(gen): $(common.l.cpp-options)
diff --git a/common/prepared/test.hxx b/common/prepared/test.hxx
index 734b138..7ea0ce8 100644
--- a/common/prepared/test.hxx
+++ b/common/prepared/test.hxx
@@ -23,4 +23,11 @@ struct person
unsigned short age_;
};
+#pragma db view object(person)
+struct person_view
+{
+ std::string name;
+ unsigned short age;
+};
+
#endif // TEST_HXX