From f2e4c2c70344dd1a98593cfbe9256d1b3ed54f27 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 12 Oct 2012 17:24:45 +0200 Subject: Completion of prepared query support --- common/prepared/driver.cxx | 276 ++++++++++++++++++++++++++++++++++++++++++++- common/prepared/makefile | 2 +- common/prepared/test.hxx | 7 ++ 3 files changed, 281 insertions(+), 4 deletions(-) (limited to 'common/prepared') 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 // std::auto_ptr +#include // std::auto_ptr, std::unique_ptr +#include // std::move #include #include @@ -13,6 +14,7 @@ #include #include +#include // 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 query; + + auto_ptr p (new params); + prepared_query pq ( + c.prepare_query ( + 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 prep_query; typedef odb::result result; - // Simple case: uncached query. + // Uncached query. // { transaction t (db->begin ()); unsigned short age (90); prep_query pq ( - t.connection ().prepare_query ( + db->prepare_query ( "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-val-age-query")); + + if (!pq) + { + assert (i == 1); + pq = db->prepare_query ( + "person-val-age-query", + query::age > 90); + db->cache_query (pq); + prep_query pq1 (db->lookup_query ("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-ref-age-query", age)); + + if (!pq) + { + assert (i == 1); + +#ifdef HAVE_CXX11 + unique_ptr p (new unsigned short); +#else + auto_ptr p (new unsigned short); +#endif + age = p.get (); + pq = db->prepare_query ( + "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 ("person-ref-age-query", age); + assert (false); + } + catch (const odb::prepared_type_mismatch&) + { + } + + // Parameters type mismatch. + // + try + { + int* age; + db->lookup_query ("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-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-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 p (new params); + prepared_query pq ( + c.prepare_query ( + 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-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 query; + typedef odb::prepared_query prep_query; + typedef odb::result result; + + transaction t (db->begin ()); + + unsigned short age (90); + prep_query pq ( + db->prepare_query ( + "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-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 -- cgit v1.1