aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-08-13 13:46:57 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-08-13 13:46:57 +0200
commit7b8192c9e9bfa3a228938e12daa222af3bbfa6f1 (patch)
tree2e8e8890a134086f24cda096a71a805495f9dc73
parent94845b83a38e0fdbc0bee496db058373057093c4 (diff)
Test language-embedded queries
-rw-r--r--common/query/driver.cxx247
-rw-r--r--common/query/makefile3
-rw-r--r--common/query/test.hxx30
-rw-r--r--common/query/test.std98
-rw-r--r--common/query/traits.hxx58
5 files changed, 406 insertions, 30 deletions
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<person>& r)
auto_ptr<person> 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<database> db (create_database (argc, argv));
+ typedef odb::query<person> query;
+ typedef odb::result<person> 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<person> query;
-
string name;
unsigned short age;
@@ -67,13 +76,16 @@ main (int argc, char* argv[])
db->query<person> ("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<person> (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<person> r (db->query<person> ());
+ result r (db->query<person> ());
- for (result<person>::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<person> r (db->query<person> ("ORDER BY age"));
+ result r (db->query<person> ("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<person> r (db->query<person> ("age >= 30 AND last_name = 'Doe'"));
+ result r (db->query<person> ("age >= 30 AND last = 'Doe'"));
print (r);
t.commit ();
}
- typedef odb::query<person> query;
-
// Value binding.
//
cout << "test 004" << endl;
@@ -123,10 +133,10 @@ main (int argc, char* argv[])
const char* name = "Doe";
- result<person> r (
+ result r (
db->query<person> (
"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<person> r (db->query<person> (q));
+ result r (db->query<person> (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<person> (query::married);
+ db->query<person> (query::married == true);
+
+ //db->query<person> (query::age);
+
+ db->query<person> (query::age == 30);
+ db->query<person> (query::age == age);
+ db->query<person> (query::age == query::_val (30));
+ db->query<person> (query::age == query::_val (age));
+ db->query<person> (query::age == query::_ref (age));
+ //db->query<person> (query::age == "123");
+ //db->query<person> ("123" == query::age);
+ //db->query<person> (query::age == query::_val ("123"));
+ //db->query<person> (query::age == query::_ref (name));
+ db->query<person> (query::last_name == "Doe");
+ db->query<person> (query::last_name == name);
+ db->query<person> (query::last_name == query::_val ("Doe"));
+ db->query<person> (query::last_name == query::_val (name));
+ db->query<person> (query::last_name == query::_ref (name));
+ //db->query<person> (query::last_name == 30);
+ //db->query<person> (query::last_name == query::_val (30));
+ //db->query<person> (query::last_name == query::_ref (age));
+
+ db->query<person> (query::last_name.is_null ());
+ db->query<person> (query::last_name.is_not_null ());
+
+ db->query<person> (query::first_name == query::last_name);
+
+ db->query<person> (query::first_name.in ("John", "Jane"));
+ db->query<person> (query::first_name.in_range (names, names_end));
+
+ // Query operators.
+ //
+ db->query<person> (query::age == 30 && query::last_name == "Doe");
+ db->query<person> (query::age == 30 || query::last_name == "Doe");
+ db->query<person> (!(query::age == 30 || query::last_name == "Doe"));
+ db->query<person> ((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<person> (query::middle_name.is_null ()));
+ print (r);
+ r = db->query<person> (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<person> (query::married));
+ print (r);
+ r = db->query<person> (!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<person> (query::last_name == "Doe"));
+ print (r);
+ r = db->query<person> (query::last_name == query::_val (name));
+ print (r);
+ query q (query::last_name == query::_ref (name));
+ name = "Doe";
+ r = db->query<person> (q);
+ print (r);
+ t.commit ();
+ }
+
+ // Test column operators (==, !=, <, >, <=, >=).
+ //
+ cout << "test 009" << endl;
+ {
+ transaction t (db->begin_transaction ());
+
+ // ==
+ //
+ result r (db->query<person> (query::last_name == "Doe"));
+ print (r);
+
+ // !=
+ //
+ r = db->query<person> (query::last_name != "Doe");
+ print (r);
+
+ // <
+ //
+ r = db->query<person> (query::age < 31);
+ print (r);
+
+ // >
+ //
+ r = db->query<person> (query::age > 30);
+ print (r);
+
+ // <=
+ //
+ r = db->query<person> (query::age <= 30);
+ print (r);
+
+ // >=
+ //
+ r = db->query<person> (query::age >= 31);
+ print (r);
+
+ t.commit ();
+ }
+
+ // Test query operators (&&, ||, (), !, +).
+ //
+ cout << "test 010" << endl;
+ {
+ transaction t (db->begin_transaction ());
+
+ // &&
+ //
+ result r (db->query<person> (
+ query::last_name == "Doe" && query::age == 29));
+ print (r);
+
+ // ||
+ //
+ r = db->query<person> (query::last_name == "Doe" || query::age == 31);
+ print (r);
+
+ // ()
+ //
+ r = db->query<person> (
+ (query::last_name != "Doe" || query::age == 29) && query::married);
+ print (r);
+
+ // !=
+ //
+ r = db->query<person> (!(query::last_name == "Doe"));
+ print (r);
+
+ // +
+ //
+ r = db->query<person> ((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<person> (query::first_name.in ("John", "Jane")));
+ print (r);
+
+ r = db->query<person> (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<person> (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<person> (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 <string>
+#include <memory>
#include <iostream>
#include <odb/core.hxx>
+typedef std::auto_ptr<std::string> 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 <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TRAITS_HXX
+#define TRAITS_HXX
+
+#include <string>
+#include <memory>
+
+#include <odb/mysql/traits.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <>
+ class value_traits<std::auto_ptr<std::string> >
+ {
+ public:
+ typedef std::auto_ptr<std::string> type;
+ typedef std::string value_type;
+ static const image_id_type image_id = id_string;
+
+ static void
+ set_value (std::auto_ptr<std::string>& 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<std::string>& 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