From 7b8192c9e9bfa3a228938e12daa222af3bbfa6f1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 13 Aug 2010 13:46:57 +0200 Subject: Test language-embedded queries --- common/query/driver.cxx | 247 ++++++++++++++++++++++++++++++++++++++++++++---- common/query/makefile | 3 +- common/query/test.hxx | 30 +++++- common/query/test.std | 98 +++++++++++++++++-- common/query/traits.hxx | 58 ++++++++++++ 5 files changed, 406 insertions(+), 30 deletions(-) create mode 100644 common/query/traits.hxx (limited to 'common/query') diff --git a/common/query/driver.cxx b/common/query/driver.cxx index 9a8300a..9c2f9ce 100644 --- a/common/query/driver.cxx +++ b/common/query/driver.cxx @@ -31,8 +31,12 @@ print (result& r) auto_ptr o (*i); cout << *o << endl; } + cout << endl; } +const char* names[] = { "John", "Jane", "Joe" }; +const char** names_end = names + sizeof (names)/sizeof (names[0]); + int main (int argc, char* argv[]) { @@ -40,17 +44,24 @@ main (int argc, char* argv[]) { auto_ptr db (create_database (argc, argv)); + typedef odb::query query; + typedef odb::result result; + // // { - person p1 (1, "John", "Doe", 30); - person p2 (2, "Jane", "Doe", 29); - person p3 (3, "Joe", "Dirt", 31); + person p1 (1, "John", "Doe", 30, true); + person p2 (2, "Jane", "Doe", 29, true); + person p3 (3, "Joe", "Dirt", 31, false); + p3.middle_name_.reset (new string ("Squeaky")); + person p4 (4, "Johansen", "Johansen", 32, false); + p4.middle_name_.reset (new string ("J")); transaction t (db->begin_transaction ()); db->persist (p1); db->persist (p2); db->persist (p3); + db->persist (p4); t.commit (); } @@ -58,8 +69,6 @@ main (int argc, char* argv[]) // if (false) { - typedef odb::query query; - string name; unsigned short age; @@ -67,13 +76,16 @@ main (int argc, char* argv[]) db->query ("age = " + query::_val (age)); query age_q (query::_ref (age) + " = age"); - query name_q ("first_name = " + query::_val (name)); + query name_q ("first = " + query::_val (name)); query q (age_q + "AND" + name_q); db->query (q); db->query (age_q + "OR" + name_q + "OR" + "age < " + query::_ref (age)); + + query q1 (query::_val (name)); + q1 += " = first"; } // Select-all query. @@ -81,9 +93,9 @@ main (int argc, char* argv[]) cout << "test 001" << endl; { transaction t (db->begin_transaction ()); - result r (db->query ()); + result r (db->query ()); - for (result::iterator i (r.begin ()); i != r.end (); ++i) + for (result::iterator i (r.begin ()); i != r.end (); ++i) { person p; i.load (p); @@ -98,7 +110,7 @@ main (int argc, char* argv[]) cout << "test 002" << endl; { transaction t (db->begin_transaction ()); - result r (db->query ("ORDER BY age")); + result r (db->query ("ORDER BY age")); print (r); t.commit (); } @@ -108,13 +120,11 @@ main (int argc, char* argv[]) cout << "test 003" << endl; { transaction t (db->begin_transaction ()); - result r (db->query ("age >= 30 AND last_name = 'Doe'")); + result r (db->query ("age >= 30 AND last = 'Doe'")); print (r); t.commit (); } - typedef odb::query query; - // Value binding. // cout << "test 004" << endl; @@ -123,10 +133,10 @@ main (int argc, char* argv[]) const char* name = "Doe"; - result r ( + result r ( db->query ( "age >= " + query::_ref (30) + "AND" + - "last_name = " + query::_val (name))); + "last = " + query::_val (name))); print (r); t.commit (); @@ -142,11 +152,11 @@ main (int argc, char* argv[]) unsigned short age; query q ("age >= " + query::_ref (age) + "AND" + - "last_name = " + query::_ref (name)); + "last = " + query::_ref (name)); name = "Doe"; age = 30; - result r (db->query (q)); + result r (db->query (q)); print (r); name = "Dirt"; @@ -156,6 +166,211 @@ main (int argc, char* argv[]) t.commit (); } + + // + // Language-embedded queries. + // + + // Compilation tests. + // + if (false) + { + string name; + unsigned short age; + + // Column operators. + // + query q1 (query::married); + db->query (query::married); + db->query (query::married == true); + + //db->query (query::age); + + db->query (query::age == 30); + db->query (query::age == age); + db->query (query::age == query::_val (30)); + db->query (query::age == query::_val (age)); + db->query (query::age == query::_ref (age)); + //db->query (query::age == "123"); + //db->query ("123" == query::age); + //db->query (query::age == query::_val ("123")); + //db->query (query::age == query::_ref (name)); + db->query (query::last_name == "Doe"); + db->query (query::last_name == name); + db->query (query::last_name == query::_val ("Doe")); + db->query (query::last_name == query::_val (name)); + db->query (query::last_name == query::_ref (name)); + //db->query (query::last_name == 30); + //db->query (query::last_name == query::_val (30)); + //db->query (query::last_name == query::_ref (age)); + + db->query (query::last_name.is_null ()); + db->query (query::last_name.is_not_null ()); + + db->query (query::first_name == query::last_name); + + db->query (query::first_name.in ("John", "Jane")); + db->query (query::first_name.in_range (names, names_end)); + + // Query operators. + // + db->query (query::age == 30 && query::last_name == "Doe"); + db->query (query::age == 30 || query::last_name == "Doe"); + db->query (!(query::age == 30 || query::last_name == "Doe")); + db->query ((query::last_name == "Doe") + "ORDER BY age"); + } + + // Test is_null/is_not_null. + // + cout << "test 006" << endl; + { + transaction t (db->begin_transaction ()); + result r (db->query (query::middle_name.is_null ())); + print (r); + r = db->query (query::middle_name.is_not_null ()); + print (r); + t.commit (); + } + + // Test boolean columns. + // + cout << "test 007" << endl; + { + transaction t (db->begin_transaction ()); + result r (db->query (query::married)); + print (r); + r = db->query (!query::married); + print (r); + t.commit (); + } + + // Test implicit by-value, explicit by-value, and by-reference. + // + cout << "test 008" << endl; + { + string name ("Dirt"); + + transaction t (db->begin_transaction ()); + result r (db->query (query::last_name == "Doe")); + print (r); + r = db->query (query::last_name == query::_val (name)); + print (r); + query q (query::last_name == query::_ref (name)); + name = "Doe"; + r = db->query (q); + print (r); + t.commit (); + } + + // Test column operators (==, !=, <, >, <=, >=). + // + cout << "test 009" << endl; + { + transaction t (db->begin_transaction ()); + + // == + // + result r (db->query (query::last_name == "Doe")); + print (r); + + // != + // + r = db->query (query::last_name != "Doe"); + print (r); + + // < + // + r = db->query (query::age < 31); + print (r); + + // > + // + r = db->query (query::age > 30); + print (r); + + // <= + // + r = db->query (query::age <= 30); + print (r); + + // >= + // + r = db->query (query::age >= 31); + print (r); + + t.commit (); + } + + // Test query operators (&&, ||, (), !, +). + // + cout << "test 010" << endl; + { + transaction t (db->begin_transaction ()); + + // && + // + result r (db->query ( + query::last_name == "Doe" && query::age == 29)); + print (r); + + // || + // + r = db->query (query::last_name == "Doe" || query::age == 31); + print (r); + + // () + // + r = db->query ( + (query::last_name != "Doe" || query::age == 29) && query::married); + print (r); + + // != + // + r = db->query (!(query::last_name == "Doe")); + print (r); + + // + + // + r = db->query ((query::last_name == "Doe") + "ORDER BY age"); + print (r); + + t.commit (); + } + + // Test in/in_range. + // + cout << "test 011" << endl; + { + transaction t (db->begin_transaction ()); + + result r (db->query (query::first_name.in ("John", "Jane"))); + print (r); + + r = db->query (query::first_name.in_range (names, names_end)); + print (r); + + t.commit (); + } + + // Test column-to-column comparison. + // + cout << "test 012" << endl; + { + transaction t (db->begin_transaction ()); + result r (db->query (query::first_name == query::last_name)); + print (r); + t.commit (); + } + + // Test value_traits::type != value_traits::value_type. + // + cout << "test 013" << endl; + { + transaction t (db->begin_transaction ()); + result r (db->query (query::middle_name == "Squeaky")); + print (r); + t.commit (); + } } catch (const odb::exception& e) { diff --git a/common/query/makefile b/common/query/makefile index 276b948..f5726a1 100644 --- a/common/query/makefile +++ b/common/query/makefile @@ -34,7 +34,8 @@ gen := $(addprefix $(out_base)/,$(genf)) $(gen): $(odb) $(gen): odb := $(odb) -$(gen): odb_options += --database $(db_id) --generate-schema +$(gen): odb_options += --database $(db_id) --generate-schema \ +--hxx-prologue '\\\#include "traits.hxx"' $(gen): cpp_options := -I$(out_base) $(gen): $(common.l.cpp-options) diff --git a/common/query/test.hxx b/common/query/test.hxx index a923458..34c489d 100644 --- a/common/query/test.hxx +++ b/common/query/test.hxx @@ -7,18 +7,26 @@ #define TEST_HXX #include +#include #include #include +typedef std::auto_ptr string_ptr; // @@ tmp + #pragma odb object struct person { person (unsigned long id, const std::string& fn, const std::string& ln, - unsigned short age) - : id_ (id), first_name_ (fn), last_name_ (ln), age_ (age) + unsigned short age, + bool married) + : id_ (id), + first_name_ (fn), + last_name_ (ln), + age_ (age), + married_ (married) { } @@ -29,15 +37,31 @@ struct person #pragma odb id unsigned long id_; + #pragma odb column ("first") std::string first_name_; + + #pragma odb column ("middle") type ("TEXT") + string_ptr middle_name_; + + #pragma odb column ("last") std::string last_name_; + unsigned short age_; + bool married_; }; inline std::ostream& operator<< (std::ostream& os, const person& p) { - return os << p.first_name_ << ' ' << p.last_name_ << ' ' << p.age_; + os << p.first_name_; + + if (p.middle_name_.get () != 0) + os << ' ' << *p.middle_name_; + + os << ' ' << p.last_name_ << ' ' << p.age_ << + (p.married_ ? " married" : " single"); + + return os; } #endif // TEST_HXX diff --git a/common/query/test.std b/common/query/test.std index 0235af1..e065765 100644 --- a/common/query/test.std +++ b/common/query/test.std @@ -1,15 +1,93 @@ test 001 -John Doe 30 -Jane Doe 29 -Joe Dirt 31 +John Doe 30 married +Jane Doe 29 married +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single test 002 -Jane Doe 29 -John Doe 30 -Joe Dirt 31 +Jane Doe 29 married +John Doe 30 married +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + test 003 -John Doe 30 +John Doe 30 married + test 004 -John Doe 30 +John Doe 30 married + test 005 -John Doe 30 -Joe Dirt 31 +John Doe 30 married + +Joe Squeaky Dirt 31 single + +test 006 +John Doe 30 married +Jane Doe 29 married + +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + +test 007 +John Doe 30 married +Jane Doe 29 married + +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + +test 008 +John Doe 30 married +Jane Doe 29 married + +Joe Squeaky Dirt 31 single + +John Doe 30 married +Jane Doe 29 married + +test 009 +John Doe 30 married +Jane Doe 29 married + +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + +John Doe 30 married +Jane Doe 29 married + +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + +John Doe 30 married +Jane Doe 29 married + +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + +test 010 +Jane Doe 29 married + +John Doe 30 married +Jane Doe 29 married +Joe Squeaky Dirt 31 single + +Jane Doe 29 married + +Joe Squeaky Dirt 31 single +Johansen J Johansen 32 single + +Jane Doe 29 married +John Doe 30 married + +test 011 +John Doe 30 married +Jane Doe 29 married + +John Doe 30 married +Jane Doe 29 married +Joe Squeaky Dirt 31 single + +test 012 +Johansen J Johansen 32 single + +test 013 +Joe Squeaky Dirt 31 single + diff --git a/common/query/traits.hxx b/common/query/traits.hxx new file mode 100644 index 0000000..39d2ca4 --- /dev/null +++ b/common/query/traits.hxx @@ -0,0 +1,58 @@ +// file : common/query/traits.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef TRAITS_HXX +#define TRAITS_HXX + +#include +#include + +#include + +namespace odb +{ + namespace mysql + { + template <> + class value_traits > + { + public: + typedef std::auto_ptr type; + typedef std::string value_type; + static const image_id_type image_id = id_string; + + static void + set_value (std::auto_ptr& v, + const char* s, + std::size_t n, + bool is_null) + { + v.reset (is_null ? 0 : new std::string (s, n)); + } + + static void + set_image (odb::buffer& b, + std::size_t& n, + bool& is_null, + const std::auto_ptr& v) + { + is_null = v.get () == 0; + + if (!is_null) + { + n = v->size (); + + if (n > b.capacity ()) + b.capacity (n); + + if (n != 0) + std::memcpy (b.data (), v->c_str (), n); + } + } + }; + } +} + +#endif // TRAITS_HXX -- cgit v1.1