summaryrefslogtreecommitdiff
path: root/odb-tests/boost
diff options
context:
space:
mode:
Diffstat (limited to 'odb-tests/boost')
-rw-r--r--odb-tests/boost/buildfile10
-rw-r--r--odb-tests/boost/common/multi-index/buildfile43
-rw-r--r--odb-tests/boost/common/multi-index/driver.cxx191
-rw-r--r--odb-tests/boost/common/multi-index/test.hxx113
-rw-r--r--odb-tests/boost/common/multi-index/testscript53
-rw-r--r--odb-tests/boost/common/optional/buildfile44
-rw-r--r--odb-tests/boost/common/optional/driver.cxx76
-rw-r--r--odb-tests/boost/common/optional/test.hxx31
-rw-r--r--odb-tests/boost/common/optional/testscript53
-rw-r--r--odb-tests/boost/common/smart-ptr/buildfile44
-rw-r--r--odb-tests/boost/common/smart-ptr/driver.cxx205
-rw-r--r--odb-tests/boost/common/smart-ptr/test.hxx82
-rw-r--r--odb-tests/boost/common/smart-ptr/testscript53
-rw-r--r--odb-tests/boost/common/unordered/buildfile43
-rw-r--r--odb-tests/boost/common/unordered/driver.cxx214
-rw-r--r--odb-tests/boost/common/unordered/test.hxx113
-rw-r--r--odb-tests/boost/common/unordered/testscript53
-rw-r--r--odb-tests/boost/common/uuid/buildfile49
-rw-r--r--odb-tests/boost/common/uuid/driver.cxx71
-rw-r--r--odb-tests/boost/common/uuid/test.hxx37
-rw-r--r--odb-tests/boost/common/uuid/testscript53
-rw-r--r--odb-tests/boost/mssql/date-time/buildfile36
-rw-r--r--odb-tests/boost/mssql/date-time/driver.cxx160
-rw-r--r--odb-tests/boost/mssql/date-time/test.hxx58
-rw-r--r--odb-tests/boost/mssql/date-time/testscript11
-rw-r--r--odb-tests/boost/mysql/date-time/buildfile40
-rw-r--r--odb-tests/boost/mysql/date-time/driver.cxx220
-rw-r--r--odb-tests/boost/mysql/date-time/test.hxx65
-rw-r--r--odb-tests/boost/mysql/date-time/testscript11
-rw-r--r--odb-tests/boost/oracle/date-time/buildfile35
-rw-r--r--odb-tests/boost/oracle/date-time/driver.cxx138
-rw-r--r--odb-tests/boost/oracle/date-time/test.hxx42
-rw-r--r--odb-tests/boost/oracle/date-time/testscript11
-rw-r--r--odb-tests/boost/pgsql/date-time/buildfile39
-rw-r--r--odb-tests/boost/pgsql/date-time/driver.cxx159
-rw-r--r--odb-tests/boost/pgsql/date-time/test.hxx39
-rw-r--r--odb-tests/boost/pgsql/date-time/testscript11
-rw-r--r--odb-tests/boost/sqlite/date-time/buildfile35
-rw-r--r--odb-tests/boost/sqlite/date-time/driver.cxx210
-rw-r--r--odb-tests/boost/sqlite/date-time/test.hxx57
-rw-r--r--odb-tests/boost/sqlite/date-time/testscript9
41 files changed, 3017 insertions, 0 deletions
diff --git a/odb-tests/boost/buildfile b/odb-tests/boost/buildfile
new file mode 100644
index 0000000..ca73102
--- /dev/null
+++ b/odb-tests/boost/buildfile
@@ -0,0 +1,10 @@
+# file : boost/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+./: common/
+
+./: mysql/: include = ($mysql && !$multi)
+./: sqlite/: include = ($sqlite && !$multi)
+./: pgsql/: include = ($pgsql && !$multi)
+./: oracle/: include = ($oracle && !$multi)
+./: mssql/: include = ($mssql && !$multi)
diff --git a/odb-tests/boost/common/multi-index/buildfile b/odb-tests/boost/common/multi-index/buildfile
new file mode 100644
index 0000000..ff8ab37
--- /dev/null
+++ b/odb-tests/boost/common/multi-index/buildfile
@@ -0,0 +1,43 @@
+# file : boost/common/multi-index/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-multi-index%lib{boost_multi_index}
+
+libs =
+
+for db: $databases
+ import libs += libodb-$db%lib{odb-$db}
+
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb -test-odb-*} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+for db: $databases
+{
+ exe{driver}: {hxx ixx cxx}{test-odb-$db}: include = $multi
+ <{hxx ixx cxx}{test-odb-$db}>: hxx{test} libue{test-meta}
+}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_multi_index_ \
+ --profile boost/multi-index \
+ --generate-schema
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{database-client}: include = adhoc
diff --git a/odb-tests/boost/common/multi-index/driver.cxx b/odb-tests/boost/common/multi-index/driver.cxx
new file mode 100644
index 0000000..68a022e
--- /dev/null
+++ b/odb-tests/boost/common/multi-index/driver.cxx
@@ -0,0 +1,191 @@
+// file : boost/common/multi-index/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test Boost multi-index container persistence.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ {
+ using namespace odb;
+
+ assert (odb::access::container_traits<int_lst>::kind == ck_ordered);
+ assert (odb::access::container_traits<int_vec>::kind == ck_ordered);
+ assert (odb::access::container_traits<int_set>::kind == ck_set);
+
+ assert (odb::access::container_traits<int_lst_set>::kind == ck_ordered);
+ assert (odb::access::container_traits<comp_set_vec>::kind == ck_ordered);
+ assert (odb::access::container_traits<comp_set_set>::kind == ck_set);
+ }
+
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ for (unsigned short i (0); i < 2; ++i)
+ {
+ object empty ("empty"), med ("medium"), full ("full");
+
+ //
+ // empty
+ //
+
+ //
+ // med
+ //
+ med.il.push_back (234);
+ med.il.push_back (123);
+
+ med.iv.push_back (234);
+ med.iv.push_back (123);
+
+ med.is.insert (234);
+ med.is.insert (123);
+
+ med.ils.push_back (234);
+ med.ils.push_back (123);
+
+ med.csv.insert (comp (234, "bcd"));
+ med.csv.insert (comp (123, "abc"));
+
+ med.css.insert (comp (234, "bcd"));
+ med.css.insert (comp (123, "abc"));
+
+ //
+ // full
+ //
+ full.il.push_back (2345);
+ full.il.push_back (1234);
+ full.il.push_back (3456);
+
+ full.iv.push_back (2345);
+ full.iv.push_back (1234);
+ full.iv.push_back (3456);
+
+ full.is.insert (2345);
+ full.is.insert (1234);
+ full.is.insert (3456);
+
+ full.ils.push_back (2345);
+ full.ils.push_back (1234);
+ full.ils.push_back (3456);
+
+ full.csv.insert (comp (234, "bcde"));
+ full.csv.insert (comp (123, "abcd"));
+ full.csv.insert (comp (234, "cdef"));
+
+ full.css.insert (comp (234, "bcde"));
+ full.css.insert (comp (123, "abcd"));
+ full.css.insert (comp (234, "cdef"));
+
+ // persist
+ //
+ {
+ transaction t (db->begin ());
+ db->persist (empty);
+ db->persist (med);
+ db->persist (full);
+ t.commit ();
+ }
+
+ // load & check
+ //
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> e (db->load<object> ("empty"));
+ unique_ptr<object> m (db->load<object> ("medium"));
+ unique_ptr<object> f (db->load<object> ("full"));
+ t.commit ();
+
+ assert (empty == *e);
+ assert (med == *m);
+ assert (full == *f);
+ }
+
+ // empty
+ //
+ empty.il.push_back (12);
+ empty.iv.push_back (12);
+ empty.is.insert (12);
+ empty.ils.push_back (12);
+ empty.csv.insert (comp (12, "ab"));
+ empty.css.insert (comp (12, "ab"));
+
+ // med
+ //
+ med.il.clear ();
+ med.iv.clear ();
+ med.is.clear ();
+ med.ils.clear ();
+ med.csv.clear ();
+ med.css.clear ();
+
+ // full
+ //
+ full.il.push_back (4567);
+ full.iv.push_back (4567);
+ full.is.insert (4567);
+ full.ils.push_back (4567);
+ full.csv.insert (comp (4567, "defg"));
+ full.css.insert (comp (4567, "defg"));
+
+ // update
+ //
+ {
+ transaction t (db->begin ());
+ db->update (empty);
+ db->update (med);
+ db->update (full);
+ t.commit ();
+ }
+
+ // load & check
+ //
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> e (db->load<object> ("empty"));
+ unique_ptr<object> m (db->load<object> ("medium"));
+ unique_ptr<object> f (db->load<object> ("full"));
+ t.commit ();
+
+ assert (empty == *e);
+ assert (med == *m);
+ assert (full == *f);
+ }
+
+ // erase
+ //
+ if (i == 0)
+ {
+ transaction t (db->begin ());
+ db->erase<object> ("empty");
+ db->erase<object> ("medium");
+ db->erase<object> ("full");
+ t.commit ();
+ }
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
diff --git a/odb-tests/boost/common/multi-index/test.hxx b/odb-tests/boost/common/multi-index/test.hxx
new file mode 100644
index 0000000..22b9ea4
--- /dev/null
+++ b/odb-tests/boost/common/multi-index/test.hxx
@@ -0,0 +1,113 @@
+// file : boost/common/multi-index/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+
+#include <odb/core.hxx>
+
+namespace mi = boost::multi_index;
+
+#pragma db value
+struct comp
+{
+ comp () {}
+ comp (int n, const std::string& s) : num (n), str (s) {}
+
+ #pragma db column("number")
+ int num;
+ std::string str;
+};
+
+inline bool
+operator== (const comp& x, const comp& y)
+{
+ return x.num == y.num && x.str == y.str;
+}
+
+typedef
+mi::multi_index_container<
+ int,
+ mi::indexed_by<mi::sequenced<> >
+> int_lst;
+
+typedef
+mi::multi_index_container<
+ int,
+ mi::indexed_by<mi::random_access<> >
+> int_vec;
+
+typedef
+mi::multi_index_container<
+ int,
+ mi::indexed_by<mi::ordered_unique<mi::identity<int> > >
+> int_set;
+
+typedef
+mi::multi_index_container<
+ int,
+ mi::indexed_by<
+ mi::sequenced<>,
+ mi::ordered_unique<mi::identity<int> >
+ >
+> int_lst_set;
+
+typedef
+mi::multi_index_container<
+ comp,
+ mi::indexed_by<
+ mi::ordered_unique<mi::member<comp, std::string, &comp::str> >,
+ mi::random_access<>
+ >
+> comp_set_vec;
+
+typedef
+mi::multi_index_container<
+ comp,
+ mi::indexed_by<
+ mi::ordered_unique<mi::member<comp, int, &comp::num> >,
+ mi::ordered_unique<mi::member<comp, std::string, &comp::str> >
+ >
+> comp_set_set;
+
+#pragma db object
+struct object
+{
+ object () {}
+ object (const std::string& id): id (id) {}
+
+ #pragma db id
+ std::string id;
+
+ int_lst il;
+ int_lst iv;
+ int_set is;
+
+ int_lst_set ils;
+ comp_set_vec csv;
+ comp_set_set css;
+};
+
+inline bool
+operator== (const object& x, const object& y)
+{
+ return
+ x.id == y.id &&
+
+ x.il == y.il &&
+ x.iv == y.iv &&
+ x.is == y.is &&
+
+ x.ils == y.ils &&
+ x.csv == y.csv &&
+ x.css == y.css;
+}
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/common/multi-index/testscript b/odb-tests/boost/common/multi-index/testscript
new file mode 100644
index 0000000..c86fcaa
--- /dev/null
+++ b/odb-tests/boost/common/multi-index/testscript
@@ -0,0 +1,53 @@
+# file : boost/common/multi-index/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+
+: mysql
+:
+if $mysql
+{
+ .include ../../../mysql.testscript
+
+ $create_schema;
+ $*
+}
+
+: sqlite
+:
+if $sqlite
+{
+ .include ../../../sqlite.testscript
+
+ $*
+}
+
+: pgsql
+:
+if $pgsql
+{
+ .include ../../../pgsql.testscript
+
+ $create_schema;
+ $*
+}
+
+: oracle
+:
+if $oracle
+{
+ .include ../../../oracle.testscript
+
+ $create_schema;
+ $*
+}
+
+: mssql
+:
+if $mssql
+{
+ .include ../../../mssql.testscript
+
+ $create_schema;
+ $*
+}
diff --git a/odb-tests/boost/common/optional/buildfile b/odb-tests/boost/common/optional/buildfile
new file mode 100644
index 0000000..3e07b95
--- /dev/null
+++ b/odb-tests/boost/common/optional/buildfile
@@ -0,0 +1,44 @@
+# file : boost/common/optional/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-optional%lib{boost_optional}
+
+libs =
+
+for db: $databases
+ import libs += libodb-$db%lib{odb-$db}
+
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb -test-odb-*} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+for db: $databases
+{
+ exe{driver}: {hxx ixx cxx}{test-odb-$db}: include = $multi
+ <{hxx ixx cxx}{test-odb-$db}>: hxx{test} libue{test-meta}
+}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_optional_ \
+ --profile boost/optional \
+ --generate-schema \
+ --generate-query
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{database-client}: include = adhoc
diff --git a/odb-tests/boost/common/optional/driver.cxx b/odb-tests/boost/common/optional/driver.cxx
new file mode 100644
index 0000000..b256032
--- /dev/null
+++ b/odb-tests/boost/common/optional/driver.cxx
@@ -0,0 +1,76 @@
+// file : boost/common/optional/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost::optional persistence.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ {
+ object o1 (1);
+ object o2 (2);
+ o2.str = "abc";
+
+ transaction t (db->begin ());
+ db->persist (o1);
+ db->persist (o2);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> o1 (db->load<object> (1));
+ unique_ptr<object> o2 (db->load<object> (2));
+ t.commit ();
+
+ assert (!o1->str);
+ assert (o2->str && *o2->str == "abc");
+ }
+
+ {
+ typedef odb::query<object> query;
+ typedef odb::result<object> result;
+
+ transaction t (db->begin ());
+
+ {
+ result r (db->query<object> (query::str.is_null ()));
+ assert (!r.empty ());
+ }
+
+ {
+ result r (db->query<object> (query::str == "abc"));
+ assert (!r.empty ());
+ }
+
+ t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
diff --git a/odb-tests/boost/common/optional/test.hxx b/odb-tests/boost/common/optional/test.hxx
new file mode 100644
index 0000000..65d951e
--- /dev/null
+++ b/odb-tests/boost/common/optional/test.hxx
@@ -0,0 +1,31 @@
+// file : boost/common/optional/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <string>
+
+#include <boost/optional.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object (unsigned long id)
+ : id_ (id)
+ {
+ }
+
+ object ()
+ {
+ }
+
+ #pragma db id
+ unsigned long id_;
+
+ boost::optional<std::string> str;
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/common/optional/testscript b/odb-tests/boost/common/optional/testscript
new file mode 100644
index 0000000..b24c252
--- /dev/null
+++ b/odb-tests/boost/common/optional/testscript
@@ -0,0 +1,53 @@
+# file : boost/common/optional/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+
+: mysql
+:
+if $mysql
+{
+ .include ../../../mysql.testscript
+
+ $create_schema;
+ $*
+}
+
+: sqlite
+:
+if $sqlite
+{
+ .include ../../../sqlite.testscript
+
+ $*
+}
+
+: pgsql
+:
+if $pgsql
+{
+ .include ../../../pgsql.testscript
+
+ $create_schema;
+ $*
+}
+
+: oracle
+:
+if $oracle
+{
+ .include ../../../oracle.testscript
+
+ $create_schema;
+ $*
+}
+
+: mssql
+:
+if $mssql
+{
+ .include ../../../mssql.testscript
+
+ $create_schema;
+ $*
+}
diff --git a/odb-tests/boost/common/smart-ptr/buildfile b/odb-tests/boost/common/smart-ptr/buildfile
new file mode 100644
index 0000000..9dfafeb
--- /dev/null
+++ b/odb-tests/boost/common/smart-ptr/buildfile
@@ -0,0 +1,44 @@
+# file : boost/common/smart-ptr/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-smart-ptr%lib{boost_smart_ptr}
+
+libs =
+
+for db: $databases
+ import libs += libodb-$db%lib{odb-$db}
+
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb -test-odb-*} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+for db: $databases
+{
+ exe{driver}: {hxx ixx cxx}{test-odb-$db}: include = $multi
+ <{hxx ixx cxx}{test-odb-$db}>: hxx{test} libue{test-meta}
+}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_smart_ptr_ \
+ --profile boost/smart-ptr \
+ --generate-schema \
+ --generate-session
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{database-client}: include = adhoc
diff --git a/odb-tests/boost/common/smart-ptr/driver.cxx b/odb-tests/boost/common/smart-ptr/driver.cxx
new file mode 100644
index 0000000..c7697c5
--- /dev/null
+++ b/odb-tests/boost/common/smart-ptr/driver.cxx
@@ -0,0 +1,205 @@
+// file : boost/common/smart-ptr/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost smart pointers.
+//
+
+#include <memory> // std::unique_ptr
+#include <utility> // std::move()
+#include <iostream>
+
+#include <odb/database.hxx>
+#include <odb/session.hxx>
+#include <odb/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+using namespace odb::boost;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ using boost::shared_ptr;
+
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ shared_ptr<cont> c1 (new cont (1));
+ {
+ transaction t (db->begin ());
+ db->persist (c1);
+ t.commit ();
+ }
+
+ // Test comparison operators.
+ //
+ {
+ assert (lazy_shared_ptr<cont> () == lazy_shared_ptr<cont> ());
+ assert (lazy_shared_ptr<cont> () != lazy_shared_ptr<cont> (c1));
+ assert (lazy_shared_ptr<cont> (c1) == lazy_shared_ptr<cont> (c1));
+
+ lazy_shared_ptr<cont> lc1 (*db, 1);
+ assert (lc1 != lazy_shared_ptr<cont> ());
+ assert (lc1 == lazy_shared_ptr<cont> (*db, c1));
+
+ shared_ptr<cont> c2 (new cont (2));
+ assert (lc1 != lazy_shared_ptr<cont> (*db, c2));
+ }
+
+ // Test swap.
+ //
+ {
+ lazy_shared_ptr<cont> lx (*db, 1), ly;
+ assert (lx == lazy_shared_ptr<cont> (*db, c1));
+
+ swap (lx, ly);
+ assert (lx == lazy_shared_ptr<cont> ());
+ assert (ly == lazy_shared_ptr<cont> (*db, c1));
+ }
+
+ // Test assignment from unique_ptr.
+ //
+ {
+ cont* p = new cont (3);
+ unique_ptr<cont> a (p);
+ lazy_shared_ptr<cont> l;
+ l = move (a);
+
+ assert (l.get() == p);
+ assert (!a.get ());
+ }
+
+ shared_ptr<obj> o1 (new obj (1));
+ shared_ptr<obj> o2 (new obj (2));
+ shared_ptr<obj> o3 (new obj (3));
+ shared_ptr<obj> o4 (new obj (4));
+ shared_ptr<cont> c2 (new cont (2));
+
+ o1->c = c1;
+ o2->c = c1;
+ o3->c = c2;
+ o4->c = c2;
+
+ // Persist.
+ //
+ {
+ transaction t (db->begin ());
+
+ db->persist (o1);
+ db->persist (o2);
+ db->persist (o3);
+ db->persist (o4);
+ db->persist (c2);
+
+ t.commit ();
+ }
+
+ // Load.
+ //
+ {
+ session s;
+ transaction t (db->begin ());
+
+ shared_ptr<cont> c (db->load<cont> (1));
+ shared_ptr<obj> o (db->load<obj> (1));
+
+ // Ensure that lazy pointers are present but not loaded.
+ //
+ assert (c->o.size () == 2);
+ assert (!c->o[0].loaded ());
+ assert (!c->o[1].loaded ());
+ assert (!o->c.loaded ());
+
+ // Ensure that the correct object IDs were loaded.
+ //
+ assert (c->o[0].object_id<obj> () == 1);
+ assert (c->o[1].object_id<obj> () == 2);
+ assert (o->c.object_id<obj> () == 1);
+
+ // Load the lazy pointer targets ensuring that the loaded
+ // targets correspond to the cached session objects.
+ //
+ shared_ptr<cont> cl (o->c.load ());
+ shared_ptr<obj> ol (c->o[0].load ());
+
+ assert (c->o[0].loaded ());
+ assert (o->c.loaded ());
+
+ assert (cl == c);
+ assert (ol == o);
+
+ t.commit ();
+ }
+
+ // Test lazy weak locking and reloading.
+ //
+ {
+ // No session.
+ //
+ transaction t (db->begin ());
+ shared_ptr<cont> c (db->load<cont> (1));
+
+ // Lock.
+ //
+ assert (!c->o[1].loaded ());
+ lazy_shared_ptr<obj> l (c->o[1].lock ());
+ assert (!l.loaded ());
+ assert (l.object_id<obj> () == c->o[1].object_id<obj> ());
+
+ // Reload.
+ //
+ assert (!c->o[1].loaded ());
+
+ shared_ptr<obj> ol (c->o[1].load ());
+ assert (c->o[1].loaded ());
+
+ ol.reset ();
+ assert (!c->o[1].loaded ());
+
+ ol = c->o[1].load ();
+ assert (c->o[1].loaded ());
+
+ t.commit ();
+ }
+
+ //
+ // Test shared_ptr as a value wrapper.
+ //
+
+ {
+ obj2 o1 (1);
+ obj2 o2 (2);
+ o2.str.reset (new string ("abc"));
+
+ transaction t (db->begin ());
+ db->persist (o1);
+ db->persist (o2);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ shared_ptr<obj2> o1 (db->load<obj2> (1));
+ shared_ptr<obj2> o2 (db->load<obj2> (2));
+ t.commit ();
+
+ assert (!o1->str);
+ assert (o2->str && *o2->str == "abc");
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
diff --git a/odb-tests/boost/common/smart-ptr/test.hxx b/odb-tests/boost/common/smart-ptr/test.hxx
new file mode 100644
index 0000000..26d7109
--- /dev/null
+++ b/odb-tests/boost/common/smart-ptr/test.hxx
@@ -0,0 +1,82 @@
+// file : boost/common/smart-ptr/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <string>
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+
+#include <odb/core.hxx>
+#include <odb/boost/smart-ptr/lazy-ptr.hxx>
+
+struct obj;
+
+using boost::shared_ptr;
+using odb::boost::lazy_shared_ptr;
+using odb::boost::lazy_weak_ptr;
+
+#pragma db object
+struct cont
+{
+ cont ()
+ {
+ }
+
+ cont (unsigned long id)
+ : id (id)
+ {
+ }
+
+ #pragma db id
+ unsigned long id;
+
+ typedef std::vector<lazy_weak_ptr<obj> > obj_list;
+
+ #pragma db inverse(c) value_not_null
+ obj_list o;
+};
+
+#pragma db object
+struct obj
+{
+ obj ()
+ {
+ }
+
+ obj (unsigned long id)
+ : id (id)
+ {
+ }
+
+ #pragma db id
+ unsigned long id;
+
+ #pragma db not_null
+ lazy_shared_ptr<cont> c;
+};
+
+// Test shared_ptr as a value wrapper.
+//
+#pragma db object
+struct obj2
+{
+ obj2 ()
+ {
+ }
+
+ obj2 (unsigned long id)
+ : id (id)
+ {
+ }
+
+ #pragma db id
+ unsigned long id;
+
+ #pragma db null
+ shared_ptr<std::string> str;
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/common/smart-ptr/testscript b/odb-tests/boost/common/smart-ptr/testscript
new file mode 100644
index 0000000..095e2e9
--- /dev/null
+++ b/odb-tests/boost/common/smart-ptr/testscript
@@ -0,0 +1,53 @@
+# file : boost/common/smart-ptr/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+
+: mysql
+:
+if $mysql
+{
+ .include ../../../mysql.testscript
+
+ $create_schema;
+ $*
+}
+
+: sqlite
+:
+if $sqlite
+{
+ .include ../../../sqlite.testscript
+
+ $*
+}
+
+: pgsql
+:
+if $pgsql
+{
+ .include ../../../pgsql.testscript
+
+ $create_schema;
+ $*
+}
+
+: oracle
+:
+if $oracle
+{
+ .include ../../../oracle.testscript
+
+ $create_schema;
+ $*
+}
+
+: mssql
+:
+if $mssql
+{
+ .include ../../../mssql.testscript
+
+ $create_schema;
+ $*
+}
diff --git a/odb-tests/boost/common/unordered/buildfile b/odb-tests/boost/common/unordered/buildfile
new file mode 100644
index 0000000..d7a47e7
--- /dev/null
+++ b/odb-tests/boost/common/unordered/buildfile
@@ -0,0 +1,43 @@
+# file : boost/common/unordered/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-unordered%lib{boost_unordered}
+
+libs =
+
+for db: $databases
+ import libs += libodb-$db%lib{odb-$db}
+
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb -test-odb-*} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+for db: $databases
+{
+ exe{driver}: {hxx ixx cxx}{test-odb-$db}: include = $multi
+ <{hxx ixx cxx}{test-odb-$db}>: hxx{test} libue{test-meta}
+}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_unordered_ \
+ --profile boost/unordered \
+ --generate-schema
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{database-client}: include = adhoc
diff --git a/odb-tests/boost/common/unordered/driver.cxx b/odb-tests/boost/common/unordered/driver.cxx
new file mode 100644
index 0000000..12c0c71
--- /dev/null
+++ b/odb-tests/boost/common/unordered/driver.cxx
@@ -0,0 +1,214 @@
+// file : boost/common/unordered/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test Boost unordered containers persistence.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ for (unsigned short i (0); i < 2; ++i)
+ {
+ object empty ("empty"), med ("medium"), full ("full");
+
+ //
+ // empty
+ //
+
+ //
+ // med
+ //
+
+ // set
+ //
+ med.ns.insert (123);
+ med.ns.insert (234);
+
+ med.ss.insert ("aaa");
+ med.ss.insert ("bbbb");
+
+ med.cms.insert (comp (123, "aaa"));
+ med.cms.insert (comp (234, "bbbb"));
+
+ // map
+ //
+ med.nsm[123] = "aaa";
+ med.nsm[234] = "bbbb";
+
+ med.snm["aaa"] = 123;
+ med.snm["bbbb"] = 234;
+
+ med.ncm[123] = comp (123, "aaa");
+ med.ncm[234] = comp (234, "bbbb");
+
+ med.csmm.insert (
+ comp_str_multimap::value_type (comp (123, "aaa"), "aaa"));
+ med.csmm.insert (
+ comp_str_multimap::value_type (comp (234, "bbbb"), "bbbb"));
+
+ //
+ // full
+ //
+
+ // set
+ //
+ full.ns.insert (1234);
+ full.ns.insert (2345);
+ full.ns.insert (3456);
+
+ full.ss.insert ("aaaa");
+ full.ss.insert ("bbbbb");
+ full.ss.insert ("cccccc");
+
+ full.cms.insert (comp (1234, "aaaa"));
+ full.cms.insert (comp (2345, "bbbbb"));
+ full.cms.insert (comp (3456, "cccccc"));
+
+ // map
+ //
+ full.nsm[1234] = "aaaa";
+ full.nsm[2345] = "bbbbb";
+ full.nsm[3456] = "cccccc";
+
+ full.snm["aaaa"] = 1234;
+ full.snm["bbbbb"] = 2345;
+ full.snm["cccccc"] = 3456;
+
+ full.ncm[1234] = comp (1234, "aaaa");
+ full.ncm[2345] = comp (2345, "bbbbb");
+ full.ncm[3456] = comp (3456, "cccccc");
+
+ full.csmm.insert (
+ comp_str_multimap::value_type (comp (1234, "aaaa"), "aaaa"));
+ full.csmm.insert (
+ comp_str_multimap::value_type (comp (2345, "bbbbb"), "bbbbb"));
+ full.csmm.insert (
+ comp_str_multimap::value_type (comp (3456, "cccccc"), "cccccc"));
+
+ // persist
+ //
+ {
+ transaction t (db->begin ());
+ db->persist (empty);
+ db->persist (med);
+ db->persist (full);
+ t.commit ();
+ }
+
+ // load & check
+ //
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> e (db->load<object> ("empty"));
+ unique_ptr<object> m (db->load<object> ("medium"));
+ unique_ptr<object> f (db->load<object> ("full"));
+ t.commit ();
+
+ assert (empty == *e);
+ assert (med == *m);
+ assert (full == *f);
+ }
+
+ // empty
+ //
+ empty.ns.insert (12);
+ empty.ss.insert ("aa");
+ empty.cms.insert (comp (12, "aa"));
+
+ empty.nsm[12] = "aa";
+ empty.snm["aa"] = 12;
+ empty.ncm[12] = comp (12, "aa");
+ empty.csmm.insert (
+ comp_str_multimap::value_type (comp (12, "aa"), "aa"));
+
+ // med
+ //
+ med.ns.clear ();
+ med.ss.clear ();
+ med.cms.clear ();
+
+ med.nsm.clear ();
+ med.snm.clear ();
+ med.ncm.clear ();
+ med.csmm.clear ();
+
+ // full
+ //
+ full.ns.insert (4567);
+ full.ss.insert ("ddddddd");
+ full.cms.insert (comp (4567, "ddddddd"));
+
+ full.nsm[3456] += 'c';
+ full.nsm[4567] = "ddddddd";
+ full.snm["cccccc"]++;
+ full.snm["ddddddd"] = 4567;
+ full.ncm[3456].num++;
+ full.ncm[3456].str += 'c';
+ full.ncm[4567] = comp (4567, "ddddddd");
+ full.csmm.find (comp (3456, "cccccc"))->second += "c";
+ full.csmm.insert (
+ comp_str_multimap::value_type (comp (4567, "ddddddd"), "ddddddd"));
+
+ // update
+ //
+ {
+ transaction t (db->begin ());
+ db->update (empty);
+ db->update (med);
+ db->update (full);
+ t.commit ();
+ }
+
+ // load & check
+ //
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> e (db->load<object> ("empty"));
+ unique_ptr<object> m (db->load<object> ("medium"));
+ unique_ptr<object> f (db->load<object> ("full"));
+ t.commit ();
+
+ assert (empty == *e);
+ assert (med == *m);
+ assert (full == *f);
+ }
+
+ // erase
+ //
+ if (i == 0)
+ {
+ transaction t (db->begin ());
+ db->erase<object> ("empty");
+ db->erase<object> ("medium");
+ db->erase<object> ("full");
+ t.commit ();
+ }
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
diff --git a/odb-tests/boost/common/unordered/test.hxx b/odb-tests/boost/common/unordered/test.hxx
new file mode 100644
index 0000000..cd77845
--- /dev/null
+++ b/odb-tests/boost/common/unordered/test.hxx
@@ -0,0 +1,113 @@
+// file : boost/common/unordered/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <string>
+
+#include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db value
+struct comp
+{
+ comp () {}
+ comp (int n, const std::string& s) : num (n), str (s) {}
+
+ #pragma db column("number")
+ int num;
+ std::string str;
+};
+
+inline bool
+operator== (const comp& x, const comp& y)
+{
+ return x.num == y.num && x.str == y.str;
+}
+
+inline bool
+operator!= (const comp& x, const comp& y)
+{
+ return !(x == y);
+}
+
+inline bool
+operator< (const comp& x, const comp& y)
+{
+ return x.num != y.num ? x.num < y.num : x.str < y.str;
+}
+
+inline std::size_t
+hash_value (const comp& x)
+{
+ std::size_t seed = 0;
+ boost::hash_combine (seed, x.num);
+ boost::hash_combine (seed, x.str);
+ return seed;
+}
+
+using boost::unordered_set;
+using boost::unordered_multiset;
+
+typedef unordered_set<int> num_set;
+typedef unordered_set<std::string> str_set;
+typedef unordered_multiset<comp> comp_multiset;
+
+using boost::unordered_map;
+using boost::unordered_multimap;
+
+typedef unordered_map<int, std::string> num_str_map;
+typedef unordered_map<std::string, int> str_num_map;
+typedef unordered_map<int, comp> num_comp_map;
+typedef unordered_multimap<comp, std::string> comp_str_multimap;
+
+#pragma db object
+struct object
+{
+ object ()
+ {
+ }
+
+ object (const std::string& id)
+ : id (id)
+ {
+ }
+
+
+ #pragma db id
+ std::string id;
+
+ // set
+ //
+ num_set ns;
+ str_set ss;
+ comp_multiset cms;
+
+ // map
+ //
+ num_str_map nsm;
+ str_num_map snm;
+ num_comp_map ncm;
+ comp_str_multimap csmm;
+};
+
+inline bool
+operator== (const object& x, const object& y)
+{
+ return
+ x.id == y.id &&
+
+ x.ns == y.ns &&
+ x.ss == y.ss &&
+ x.cms == y.cms &&
+
+ x.nsm == y.nsm &&
+ x.snm == y.snm &&
+ x.ncm == y.ncm &&
+ x.csmm == y.csmm;
+}
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/common/unordered/testscript b/odb-tests/boost/common/unordered/testscript
new file mode 100644
index 0000000..d152545
--- /dev/null
+++ b/odb-tests/boost/common/unordered/testscript
@@ -0,0 +1,53 @@
+# file : boost/common/unordered/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+
+: mysql
+:
+if $mysql
+{
+ .include ../../../mysql.testscript
+
+ $create_schema;
+ $*
+}
+
+: sqlite
+:
+if $sqlite
+{
+ .include ../../../sqlite.testscript
+
+ $*
+}
+
+: pgsql
+:
+if $pgsql
+{
+ .include ../../../pgsql.testscript
+
+ $create_schema;
+ $*
+}
+
+: oracle
+:
+if $oracle
+{
+ .include ../../../oracle.testscript
+
+ $create_schema;
+ $*
+}
+
+: mssql
+:
+if $mssql
+{
+ .include ../../../mssql.testscript
+
+ $create_schema;
+ $*
+}
diff --git a/odb-tests/boost/common/uuid/buildfile b/odb-tests/boost/common/uuid/buildfile
new file mode 100644
index 0000000..32f226c
--- /dev/null
+++ b/odb-tests/boost/common/uuid/buildfile
@@ -0,0 +1,49 @@
+# file : boost/common/uuid/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-uuid%lib{boost_uuid}
+
+libs =
+
+for db: $databases
+ import libs += libodb-$db%lib{odb-$db}
+
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb -test-odb-*} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+for db: $databases
+{
+ exe{driver}: {hxx ixx cxx}{test-odb-$db}: include = $multi
+ <{hxx ixx cxx}{test-odb-$db}>: hxx{test} libue{test-meta}
+}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_uuid_ \
+ --profile boost/uuid \
+ --generate-schema \
+ --generate-query
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# @@ TMP Until https://github.com/build2-packaging/boost/issues/2 is fixed.
+#
+if ($cxx.target.class == 'windows')
+ cxx.libs += ($cxx.target.system == 'mingw32' ? -lbcrypt : bcrypt.lib)
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{database-client}: include = adhoc
diff --git a/odb-tests/boost/common/uuid/driver.cxx b/odb-tests/boost/common/uuid/driver.cxx
new file mode 100644
index 0000000..8b1018f
--- /dev/null
+++ b/odb-tests/boost/common/uuid/driver.cxx
@@ -0,0 +1,71 @@
+// file : boost/common/uuid/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test Boost UUID persistence.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <boost/uuid/uuid_generators.hpp>
+
+#include <odb/database.hxx>
+#include <odb/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+using namespace boost::uuids;
+using namespace odb::core;
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ object o (1);
+ o.uuid_ = random_generator() ();
+ o.null_ = nil_uuid ();
+ o.zero_ = nil_uuid ();
+
+ {
+ transaction t (db->begin ());
+ db->persist (o);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> p (db->load<object> (o.id_));
+ t.commit ();
+
+ assert (*p == o);
+ }
+
+ {
+ typedef odb::query<object> query;
+ typedef odb::result<object> result;
+
+ transaction t (db->begin ());
+ result r (db->query<object> (query::uuid == o.uuid_));
+ result::iterator i (r.begin ());
+ assert (i != r.end () && i->id_ == o.id_);
+ assert (++i == r.end ());
+ t.commit ();
+ }
+
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
diff --git a/odb-tests/boost/common/uuid/test.hxx b/odb-tests/boost/common/uuid/test.hxx
new file mode 100644
index 0000000..82ed95b
--- /dev/null
+++ b/odb-tests/boost/common/uuid/test.hxx
@@ -0,0 +1,37 @@
+// file : boost/common/uuid/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <boost/uuid/uuid.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object () {}
+ object (unsigned long id): id_ (id) {}
+
+ #pragma db id
+ unsigned long id_;
+
+ typedef boost::uuids::uuid uuid;
+
+ uuid uuid_;
+ uuid null_;
+
+ #pragma db not_null
+ uuid zero_;
+
+ bool operator== (const object& x) const
+ {
+ return id_ == x.id_ &&
+ uuid_ == x.uuid_ &&
+ null_ == x.null_ &&
+ zero_ == x.zero_;
+ }
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/common/uuid/testscript b/odb-tests/boost/common/uuid/testscript
new file mode 100644
index 0000000..f9e6e54
--- /dev/null
+++ b/odb-tests/boost/common/uuid/testscript
@@ -0,0 +1,53 @@
+# file : boost/common/uuid/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+
+: mysql
+:
+if $mysql
+{
+ .include ../../../mysql.testscript
+
+ $create_schema;
+ $*
+}
+
+: sqlite
+:
+if $sqlite
+{
+ .include ../../../sqlite.testscript
+
+ $*
+}
+
+: pgsql
+:
+if $pgsql
+{
+ .include ../../../pgsql.testscript
+
+ $create_schema;
+ $*
+}
+
+: oracle
+:
+if $oracle
+{
+ .include ../../../oracle.testscript
+
+ $create_schema;
+ $*
+}
+
+: mssql
+:
+if $mssql
+{
+ .include ../../../mssql.testscript
+
+ $create_schema;
+ $*
+}
diff --git a/odb-tests/boost/mssql/date-time/buildfile b/odb-tests/boost/mssql/date-time/buildfile
new file mode 100644
index 0000000..e218389
--- /dev/null
+++ b/odb-tests/boost/mssql/date-time/buildfile
@@ -0,0 +1,36 @@
+# file : boost/mssql/date-time/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+if ($build.meta_operation != 'dist')
+{
+ assert ($mssql) "mssql should be configured for this test"
+ assert (!$multi) "multi-database mode is not supported by this test"
+}
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-date-time%lib{boost_date_time}
+
+import libs = libodb-mssql%lib{odb-mssql}
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_mssql_dt_ \
+ --profile boost/date-time \
+ --generate-schema
+
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
diff --git a/odb-tests/boost/mssql/date-time/driver.cxx b/odb-tests/boost/mssql/date-time/driver.cxx
new file mode 100644
index 0000000..5d1dad8
--- /dev/null
+++ b/odb-tests/boost/mssql/date-time/driver.cxx
@@ -0,0 +1,160 @@
+// file : boost/mssql/date-time/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost date/time type persistence. SQL Server version.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/boost/date-time/exceptions.hxx>
+
+#include <odb/mssql/database.hxx>
+#include <odb/mssql/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
+using namespace odb::core;
+
+bool
+test_invalid_special_value (object&, unique_ptr<database>&);
+
+bool
+test_out_of_range_value (object&, unique_ptr<database>&);
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ object o;
+
+ // Test all valid date-time mappings.
+ //
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ o.dates.push_back (day_clock::local_day ());
+ o.dates.push_back (date (not_a_date_time));
+ o.dates.push_back (date (max_date_time));
+ o.dates.push_back (date (min_date_time));
+
+ o.times.push_back (second_clock::local_time ());
+ o.times.push_back (not_a_date_time);
+ o.times.push_back (min_date_time);
+ o.times.push_back (ptime (max_date_time));
+#endif
+
+ // In DATETIME fractional seconds are rounded to .000, .003, or .007.
+ //
+ o.times_dt.push_back (ptime (date (2012, 1, 13),
+ time_duration (11, 57, 13, 7000)));
+
+ // SMALLDATETIME doesn't have seconds (always 0).
+ //
+ o.times_sdt.push_back (ptime (date (2012, 1, 13),
+ time_duration (11, 57, 0, 0)));
+
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ o.durations.push_back (time_duration (1, 2, 3, 123456));
+ o.durations.push_back (not_a_date_time);
+#endif
+
+ {
+ transaction t (db->begin ());
+ db->persist (o);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> ol (db->load<object> (o.id));
+ t.commit ();
+
+ assert (*ol == o);
+ }
+
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ // Test invalid date mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.dates.push_back (date (neg_infin));
+ sv2.dates.push_back (date (pos_infin));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ // Test invalid ptime mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.times.push_back (neg_infin);
+ sv2.times.push_back (pos_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ // Test invalid time_duration mappings.
+ //
+ {
+ object sv1, sv2, or1;
+ sv1.durations.push_back (pos_infin);
+ sv2.durations.push_back (neg_infin);
+ or1.durations.push_back (time_duration (50, 2, 3, 123456700));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+
+ try
+ {
+ db->persist (or1);
+ assert (false);
+ }
+ catch (const odb::boost::date_time::value_out_of_range&)
+ {
+ }
+
+ t.commit ();
+ }
+#endif
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
+
+bool
+test_invalid_special_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::special_value&)
+ {
+ }
+
+ return true;
+}
diff --git a/odb-tests/boost/mssql/date-time/test.hxx b/odb-tests/boost/mssql/date-time/test.hxx
new file mode 100644
index 0000000..ed2276b
--- /dev/null
+++ b/odb-tests/boost/mssql/date-time/test.hxx
@@ -0,0 +1,58 @@
+// file : boost/mssql/date-time/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <vector>
+
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object ()
+ {
+ }
+
+ #pragma db id auto
+ unsigned long id;
+
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ std::vector<boost::gregorian::date> dates;
+
+ std::vector<boost::posix_time::ptime> times;
+#endif
+
+ #pragma db value_type("DATETIME")
+ std::vector<boost::posix_time::ptime> times_dt;
+
+ #pragma db value_type("SMALLDATETIME")
+ std::vector<boost::posix_time::ptime> times_sdt;
+
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ std::vector<boost::posix_time::time_duration> durations;
+#endif
+
+ bool
+ operator== (const object& x) const
+ {
+ return
+ id == x.id
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ && dates == x.dates
+ && times == x.times
+#endif
+ && times_dt == x.times_dt
+ && times_sdt == x.times_sdt
+#if !defined(MSSQL_SERVER_VERSION) || MSSQL_SERVER_VERSION >= 1000
+ && durations == x.durations
+#endif
+ ;
+ }
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/mssql/date-time/testscript b/odb-tests/boost/mssql/date-time/testscript
new file mode 100644
index 0000000..cae9f61
--- /dev/null
+++ b/odb-tests/boost/mssql/date-time/testscript
@@ -0,0 +1,11 @@
+# file : boost/mssql/date-time/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+.include ../../../mssql.testscript
+
++$create_schema
+
+: basics
+:
+$*
diff --git a/odb-tests/boost/mysql/date-time/buildfile b/odb-tests/boost/mysql/date-time/buildfile
new file mode 100644
index 0000000..3573457
--- /dev/null
+++ b/odb-tests/boost/mysql/date-time/buildfile
@@ -0,0 +1,40 @@
+# file : boost/mysql/date-time/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+if ($build.meta_operation != 'dist')
+{
+ assert ($mysql) "mysql should be configured for this test"
+ assert (!$multi) "multi-database mode is not supported by this test"
+}
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-date-time%lib{boost_date_time}
+
+import libs = libodb-mysql%lib{odb-mysql}
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_mysql_dt_ \
+ --profile boost/date-time \
+ --generate-schema \
+ --generate-query
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{mysql-client}: include = adhoc
diff --git a/odb-tests/boost/mysql/date-time/driver.cxx b/odb-tests/boost/mysql/date-time/driver.cxx
new file mode 100644
index 0000000..b12ee58
--- /dev/null
+++ b/odb-tests/boost/mysql/date-time/driver.cxx
@@ -0,0 +1,220 @@
+// file : boost/mysql/date-time/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost date/time type persistence. MySQL version.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/mysql/database.hxx>
+#include <odb/mysql/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
+using namespace odb::core;
+
+bool
+test_invalid_special_value (object&, unique_ptr<database>&);
+
+bool
+test_out_of_range_value (object&, unique_ptr<database>&);
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ mysql_version v;
+ {
+ transaction t (db->begin ());
+ db->query<mysql_version> ().begin ().load (v);
+ t.commit ();
+ }
+
+ // If we are running against MySQL 5.6.4 or later alter the tables
+ // to allow sub-second precision.
+ //
+ bool fs (v.major > 5 ||
+ (v.major == 5 && (v.minor > 6 ||
+ (v.minor == 6 && v.release >= 4))));
+ if (fs)
+ {
+ transaction t (db->begin ());
+
+ db->execute ("ALTER TABLE `boost_mysql_dt_object_durations`" \
+ " MODIFY COLUMN `value` TIME(6)");
+
+ db->execute ("ALTER TABLE `boost_mysql_dt_object_times`" \
+ " MODIFY COLUMN `value` DATETIME(6)");
+
+ db->execute ("ALTER TABLE `boost_mysql_dt_object_timestamps`" \
+ " MODIFY COLUMN `value` TIMESTAMP(6) NULL");
+
+ t.commit ();
+ }
+
+ object o;
+
+ // Test all valid date-time mappings.
+ //
+ o.dates.push_back (day_clock::local_day ());
+ o.dates.push_back (date (not_a_date_time));
+ o.dates.push_back (date (max_date_time));
+ o.dates.push_back (date (min_date_time));
+
+ if (fs)
+ o.times.push_back (microsec_clock::local_time ());
+ else
+ o.times.push_back (second_clock::local_time ());
+ o.times.push_back (not_a_date_time);
+ o.times.push_back (min_date_time);
+
+ // MySQL prior to 5.6.4 does not support fraction seconds. Construct
+ // with zero fractional seconds so that comparison test does not fail
+ // for invalid reasons.
+ //
+ o.times.push_back (
+ ptime (
+ date (max_date_time),
+ time_duration (
+ ptime (max_date_time).time_of_day ().hours (),
+ ptime (max_date_time).time_of_day ().minutes (),
+ ptime (max_date_time).time_of_day ().seconds ())));
+
+ if (fs)
+ o.timestamps.push_back (microsec_clock::local_time ());
+ else
+ o.timestamps.push_back (second_clock::local_time ());
+ o.timestamps.push_back (not_a_date_time);
+
+ o.durations.push_back (time_duration (1, 2, 3));
+ if (fs)
+ o.durations.back () += time_duration (microseconds (123456));
+ o.durations.push_back (time_duration (-1, 2, 3));
+ o.durations.push_back (not_a_date_time);
+
+ {
+ transaction t (db->begin ());
+ db->persist (o);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> ol (db->load<object> (o.id));
+ t.commit ();
+
+ assert (*ol == o);
+ }
+
+ {
+ // Test invalid date mappings.
+ //
+ object sv1, sv2;
+ sv1.dates.push_back (date (neg_infin));
+ sv2.dates.push_back (date (pos_infin));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+
+ {
+ // Test invalid ptime (DATETIME) mappings.
+ //
+ object sv1, sv2;
+ sv1.times.push_back (neg_infin);
+ sv2.times.push_back (pos_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ {
+ // Test invalid ptime (TIMESTAMP) mappings.
+ //
+ object or1, or2, sv1, sv2;
+ or1.timestamps.push_back (min_date_time);
+ or2.timestamps.push_back (max_date_time);
+ sv1.timestamps.push_back (neg_infin);
+ sv2.timestamps.push_back (pos_infin);
+
+ transaction t (db->begin ());
+ assert (test_out_of_range_value (or1, db));
+ assert (test_out_of_range_value (or2, db));
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ {
+ // Test invalid time_duration mappings.
+ //
+ object or1, or2, sv1, sv2;
+ or1.durations.push_back (time_duration (850, 0, 0));
+ or2.durations.push_back (time_duration (-850, 0, 0));
+ sv1.durations.push_back (pos_infin);
+ sv2.durations.push_back (neg_infin);
+
+ transaction t (db->begin ());
+ assert (test_out_of_range_value (or1, db));
+ assert (test_out_of_range_value (or2, db));
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
+
+bool
+test_invalid_special_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::special_value&)
+ {
+ }
+
+ return true;
+}
+
+bool
+test_out_of_range_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::value_out_of_range&)
+ {
+ }
+
+ return true;
+}
diff --git a/odb-tests/boost/mysql/date-time/test.hxx b/odb-tests/boost/mysql/date-time/test.hxx
new file mode 100644
index 0000000..bf73b09
--- /dev/null
+++ b/odb-tests/boost/mysql/date-time/test.hxx
@@ -0,0 +1,65 @@
+// file : boost/mysql/date-time/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <vector>
+
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object ()
+ {
+ }
+
+ bool
+ operator== (const object& x) const
+ {
+ return
+ id == x.id &&
+ dates == x.dates &&
+ times == x.times &&
+ timestamps == x.timestamps &&
+ durations == x.durations;
+ }
+
+ #pragma db id auto
+ unsigned long id;
+
+ std::vector<boost::gregorian::date> dates;
+ std::vector<boost::posix_time::ptime> times;
+
+ // Make timestamp NULL-able to suppress the auto-initialization and
+ // auto-update characteristics of the TIMESTAMP datatype, and to
+ // allow NULL values.
+ //
+ #pragma db value_type ("TIMESTAMP") value_null
+ std::vector<boost::posix_time::ptime> timestamps;
+
+ std::vector<boost::posix_time::time_duration> durations;
+};
+
+// MySQL server version view.
+//
+#pragma db view query( \
+ "SELECT " \
+ "CAST(SUBSTRING_INDEX(@@version, '.', 1) AS UNSIGNED)," \
+ "CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(@@version, '.', 2), '.', -1) AS UNSIGNED)," \
+ "CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(@@version, '-', 1), '.', -1) AS UNSIGNED)," \
+ "@@protocol_version")
+struct mysql_version
+{
+ unsigned int major;
+ unsigned int minor;
+ unsigned int release;
+
+ unsigned int protocol;
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/mysql/date-time/testscript b/odb-tests/boost/mysql/date-time/testscript
new file mode 100644
index 0000000..2c44682
--- /dev/null
+++ b/odb-tests/boost/mysql/date-time/testscript
@@ -0,0 +1,11 @@
+# file : boost/mysql/date-time/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+.include ../../../mysql.testscript
+
++$create_schema
+
+: basics
+:
+$*
diff --git a/odb-tests/boost/oracle/date-time/buildfile b/odb-tests/boost/oracle/date-time/buildfile
new file mode 100644
index 0000000..c98e834
--- /dev/null
+++ b/odb-tests/boost/oracle/date-time/buildfile
@@ -0,0 +1,35 @@
+# file : boost/oracle/date-time/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+if ($build.meta_operation != 'dist')
+{
+ assert ($oracle) "oracle should be configured for this test"
+ assert (!$multi) "multi-database mode is not supported by this test"
+}
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-date-time%lib{boost_date_time}
+
+import libs = libodb-oracle%lib{odb-oracle}
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_or_dt_ \
+ --profile boost/date-time \
+ --generate-schema
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
diff --git a/odb-tests/boost/oracle/date-time/driver.cxx b/odb-tests/boost/oracle/date-time/driver.cxx
new file mode 100644
index 0000000..31f3f6f
--- /dev/null
+++ b/odb-tests/boost/oracle/date-time/driver.cxx
@@ -0,0 +1,138 @@
+// file : boost/oracle/date-time/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost date/time type persistence. Oracle version.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/boost/date-time/exceptions.hxx>
+
+#include <odb/oracle/database.hxx>
+#include <odb/oracle/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
+using namespace odb::core;
+
+bool
+test_invalid_special_value (object&, unique_ptr<database>&);
+
+bool
+test_out_of_range_value (object&, unique_ptr<database>&);
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ object o;
+
+ // Test all valid date-time mappings.
+ //
+ o.dates.push_back (day_clock::local_day ());
+ o.dates.push_back (date (not_a_date_time));
+ o.dates.push_back (date (max_date_time));
+ o.dates.push_back (date (min_date_time));
+
+ o.times.push_back (second_clock::local_time ());
+ o.times.push_back (not_a_date_time);
+ o.times.push_back (min_date_time);
+ o.times.push_back (ptime (max_date_time));
+
+ o.times_d.push_back (ptime (date (2012, 6, 27),
+ time_duration (14, 17, 05, 0)));
+ o.times_d.push_back (not_a_date_time);
+
+ o.durations.push_back (time_duration (1, 2, 3, 123456));
+ o.durations.push_back (time_duration (-1, 2, 3));
+ o.durations.push_back (not_a_date_time);
+
+ {
+ transaction t (db->begin ());
+ db->persist (o);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> ol (db->load<object> (o.id));
+ t.commit ();
+
+ assert (*ol == o);
+ }
+
+ // Test invalid date mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.dates.push_back (date (neg_infin));
+ sv2.dates.push_back (date (pos_infin));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ // Test invalid ptime mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.times.push_back (neg_infin);
+ sv2.times.push_back (pos_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ // Test invalid time_duration mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.durations.push_back (pos_infin);
+ sv2.durations.push_back (neg_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
+
+bool
+test_invalid_special_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::special_value&)
+ {
+ }
+
+ return true;
+}
diff --git a/odb-tests/boost/oracle/date-time/test.hxx b/odb-tests/boost/oracle/date-time/test.hxx
new file mode 100644
index 0000000..5eaab88
--- /dev/null
+++ b/odb-tests/boost/oracle/date-time/test.hxx
@@ -0,0 +1,42 @@
+// file : boost/oracle/date-time/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <vector>
+
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object ()
+ {
+ }
+
+ bool
+ operator== (const object& x) const
+ {
+ return
+ id == x.id &&
+ dates == x.dates &&
+ times == x.times &&
+ times_d == x.times_d &&
+ durations == x.durations;
+ }
+
+ #pragma db id auto
+ unsigned long id;
+
+ std::vector<boost::gregorian::date> dates;
+ std::vector<boost::posix_time::ptime> times;
+ #pragma db value_type("DATE")
+ std::vector<boost::posix_time::ptime> times_d;
+ std::vector<boost::posix_time::time_duration> durations;
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/oracle/date-time/testscript b/odb-tests/boost/oracle/date-time/testscript
new file mode 100644
index 0000000..530aaaa
--- /dev/null
+++ b/odb-tests/boost/oracle/date-time/testscript
@@ -0,0 +1,11 @@
+# file : boost/oracle/date-time/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+.include ../../../oracle.testscript
+
++$create_schema
+
+: basics
+:
+$*
diff --git a/odb-tests/boost/pgsql/date-time/buildfile b/odb-tests/boost/pgsql/date-time/buildfile
new file mode 100644
index 0000000..e0979a6
--- /dev/null
+++ b/odb-tests/boost/pgsql/date-time/buildfile
@@ -0,0 +1,39 @@
+# file : boost/pgsql/date-time/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+if ($build.meta_operation != 'dist')
+{
+ assert ($pgsql) "pgsql should be configured for this test"
+ assert (!$multi) "multi-database mode is not supported by this test"
+}
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-date-time%lib{boost_date_time}
+
+import libs = libodb-pgsql%lib{odb-pgsql}
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_pgsql_dt_ \
+ --profile boost/date-time \
+ --generate-schema
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
+
+# Testscript's run-time prerequisites.
+#
+exe{driver}: ../../../alias{pgsql-client}: include = adhoc
diff --git a/odb-tests/boost/pgsql/date-time/driver.cxx b/odb-tests/boost/pgsql/date-time/driver.cxx
new file mode 100644
index 0000000..010d5fe
--- /dev/null
+++ b/odb-tests/boost/pgsql/date-time/driver.cxx
@@ -0,0 +1,159 @@
+// file : boost/pgsql/date-time/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost date/time type persistence. PostgreSQL version.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/pgsql/database.hxx>
+#include <odb/pgsql/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
+using namespace odb::core;
+
+bool
+test_invalid_special_value (object&, unique_ptr<database>&);
+
+bool
+test_out_of_range_value (object&, unique_ptr<database>&);
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ object o;
+
+ // Test all valid date-time mappings.
+ //
+ o.dates.push_back (day_clock::local_day ());
+ o.dates.push_back (date (not_a_date_time));
+ o.dates.push_back (date (max_date_time));
+ o.dates.push_back (date (min_date_time));
+
+ o.times.push_back (microsec_clock::local_time ());
+ o.times.push_back (not_a_date_time);
+ o.times.push_back (pos_infin);
+ o.times.push_back (neg_infin);
+ o.times.push_back (ptime (date (max_date_time),
+ time_duration (16, 23, 0, 123456)));
+ o.times.push_back (ptime (date (min_date_time),
+ time_duration (3, 14, 7, 123456)));
+ o.times.push_back (ptime (date (1969, 12, 31), // Before PG epoch.
+ time_duration (23, 59, 59, 123000)));
+
+ o.durations.push_back (time_duration (0, 0, 0));
+ o.durations.push_back (time_duration (12, 3, 4, 123456));
+ o.durations.push_back (time_duration (23, 59, 59, 123456));
+ o.durations.push_back (not_a_date_time);
+
+ {
+ transaction t (db->begin ());
+ db->persist (o);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> ol (db->load<object> (o.id));
+ t.commit ();
+
+ assert (*ol == o);
+ }
+
+ {
+ // Test invalid date mappings.
+ //
+ object sv1, sv2;
+ sv1.dates.push_back (date (neg_infin));
+ sv2.dates.push_back (date (pos_infin));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ {
+ // Test invalid ptime mappings.
+ //
+ // object sv1, sv2;
+ // sv1.times.push_back (neg_infin);
+ // sv2.times.push_back (pos_infin);
+
+ // transaction t (db->begin ());
+ // assert (test_invalid_special_value (sv1, db));
+ // assert (test_invalid_special_value (sv2, db));
+ // t.commit ();
+ }
+
+ {
+ // Test invalid time_duration mappings.
+ //
+ // object or1, sv1, sv2;
+ // or1.durations.push_back (time_duration (0, 0, -1));
+ // sv1.durations.push_back (pos_infin);
+ // sv2.durations.push_back (neg_infin);
+
+ // transaction t (db->begin ());
+ // assert (test_out_of_range_value (or1, db));
+ // assert (test_invalid_special_value (sv1, db));
+ // assert (test_invalid_special_value (sv2, db));
+ // t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
+
+bool
+test_invalid_special_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::special_value&)
+ {
+ }
+
+ return true;
+}
+
+bool
+test_out_of_range_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::value_out_of_range&)
+ {
+ }
+
+ return true;
+}
diff --git a/odb-tests/boost/pgsql/date-time/test.hxx b/odb-tests/boost/pgsql/date-time/test.hxx
new file mode 100644
index 0000000..0b08093
--- /dev/null
+++ b/odb-tests/boost/pgsql/date-time/test.hxx
@@ -0,0 +1,39 @@
+// file : boost/pgsql/date-time/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <vector>
+
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object ()
+ {
+ }
+
+ bool
+ operator== (const object& x) const
+ {
+ return
+ id == x.id &&
+ dates == x.dates &&
+ times == x.times &&
+ durations == x.durations;
+ }
+
+ #pragma db id auto
+ unsigned long id;
+
+ std::vector<boost::gregorian::date> dates;
+ std::vector<boost::posix_time::ptime> times;
+ std::vector<boost::posix_time::time_duration> durations;
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/pgsql/date-time/testscript b/odb-tests/boost/pgsql/date-time/testscript
new file mode 100644
index 0000000..fd3bc0e
--- /dev/null
+++ b/odb-tests/boost/pgsql/date-time/testscript
@@ -0,0 +1,11 @@
+# file : boost/pgsql/date-time/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+.include ../../../pgsql.testscript
+
++$create_schema
+
+: basics
+:
+$*
diff --git a/odb-tests/boost/sqlite/date-time/buildfile b/odb-tests/boost/sqlite/date-time/buildfile
new file mode 100644
index 0000000..dbf398f
--- /dev/null
+++ b/odb-tests/boost/sqlite/date-time/buildfile
@@ -0,0 +1,35 @@
+# file : boost/sqlite/date-time/buildfile
+# license : GNU GPL v2; see accompanying LICENSE file
+
+if ($build.meta_operation != 'dist')
+{
+ assert ($sqlite) "sqlite should be configured for this test"
+ assert (!$multi) "multi-database mode is not supported by this test"
+}
+
+import meta_libs = libodb%lib{odb}
+import meta_libs += libodb-boost%lib{odb-boost}
+import meta_libs += libboost-date-time%lib{boost_date_time}
+
+import libs = libodb-sqlite%lib{odb-sqlite}
+import libs += lib{common}
+
+exe{driver}: {hxx cxx}{* -test-odb} {hxx ixx cxx}{test-odb} testscript
+
+# Introduce the metadata library target to make sure the libodb library is
+# resolved for the odb_compile ad hoc rule (see build/root.build for details).
+#
+libue{test-meta}: $meta_libs
+
+<{hxx ixx cxx}{test-odb}>: hxx{test} libue{test-meta}
+
+exe{driver}: libue{test-meta} $libs
+
+# Specify the ODB custom options to be used by the odb_compile ad hoc rule
+# (see build/root.build for details).
+#
+odb_options = --table-prefix boost_sqlite_dt_ \
+ --profile boost/date-time \
+ --generate-schema
+
+cxx.poptions =+ "-I$out_base" "-I$src_base"
diff --git a/odb-tests/boost/sqlite/date-time/driver.cxx b/odb-tests/boost/sqlite/date-time/driver.cxx
new file mode 100644
index 0000000..c630255
--- /dev/null
+++ b/odb-tests/boost/sqlite/date-time/driver.cxx
@@ -0,0 +1,210 @@
+// file : boost/sqlite/date-time/driver.cxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+// Test boost date/time type persistence. SQLite version.
+//
+
+#include <memory> // std::unique_ptr
+#include <iostream>
+
+#include <odb/sqlite/database.hxx>
+#include <odb/sqlite/transaction.hxx>
+
+#include <libcommon/common.hxx>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
+
+#include "test.hxx"
+#include "test-odb.hxx"
+
+#undef NDEBUG
+#include <cassert>
+
+using namespace std;
+
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
+using namespace odb::core;
+
+bool
+test_invalid_special_value (object&, unique_ptr<database>&);
+
+bool
+test_out_of_range_value (object&, unique_ptr<database>&);
+
+int
+main (int argc, char* argv[])
+{
+ try
+ {
+ unique_ptr<database> db (create_database (argc, argv));
+
+ object o;
+
+ // Test all valid date-time mappings.
+ //
+ o.dates.push_back (day_clock::local_day ());
+ o.dates.push_back (date (not_a_date_time));
+ o.dates.push_back (date (max_date_time));
+ o.dates.push_back (date (min_date_time));
+
+ o.times.push_back (second_clock::local_time ());
+ o.times.push_back (not_a_date_time);
+ o.times.push_back (min_date_time);
+ o.times.push_back (max_date_time);
+
+ o.durations.push_back (time_duration (123, 4, 5));
+ o.durations.push_back (not_a_date_time);
+
+ o.u_dates.push_back (day_clock::local_day ());
+ o.u_dates.push_back (date (not_a_date_time));
+
+ // Boost seems to handle 64 bit std::time_t incorrectly.
+ // Insert 32 bit minimum and maximum UNIX time values for now.
+ //
+ // o.u_dates.push_back (date (max_date_time));
+ // o.u_dates.push_back (date (min_date_time));
+ //
+ o.u_dates.push_back (date (2038, 1, 19));
+ o.u_dates.push_back (date (1901, 12, 14));
+
+ o.u_times.push_back (second_clock::local_time ());
+ o.u_times.push_back (not_a_date_time);
+ o.u_times.push_back (ptime (date (1930, 1, 1), time_duration (0, 0, 0)));
+
+ o.s_durations.push_back (time_duration (123, 4, 5));
+ o.s_durations.push_back (time_duration (-12, 3, 4));
+ o.s_durations.push_back (not_a_date_time);
+
+ {
+ transaction t (db->begin ());
+ db->persist (o);
+ t.commit ();
+ }
+
+ {
+ transaction t (db->begin ());
+ unique_ptr<object> ol (db->load<object> (o.id));
+ t.commit ();
+
+ assert (*ol == o);
+ }
+
+ {
+ // Test invalid date mappings.
+ //
+ object sv1, sv2;
+ sv1.dates.push_back (date (neg_infin));
+ sv2.dates.push_back (date (pos_infin));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ {
+ // Test invalid ptime mappings.
+ //
+ object sv1, sv2;
+ sv1.times.push_back (neg_infin);
+ sv2.times.push_back (pos_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ {
+ // Test invalid time_duration mappings.
+ //
+ object or1, sv1, sv2;
+ or1.durations.push_back (time_duration (0, 0, -1));
+ sv1.durations.push_back (pos_infin);
+ sv2.durations.push_back (neg_infin);
+
+ transaction t (db->begin ());
+ assert (test_out_of_range_value (or1, db));
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ {
+ // Test invalid UNIX date mappings.
+ //
+ object sv1, sv2;
+ sv1.u_dates.push_back (date (neg_infin));
+ sv2.u_dates.push_back (date (pos_infin));
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ // Test invalid UNIX times mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.u_times.push_back (pos_infin);
+ sv2.u_times.push_back (neg_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+
+ // Test invalid "seconds" duration mappings.
+ //
+ {
+ object sv1, sv2;
+ sv1.s_durations.push_back (pos_infin);
+ sv2.s_durations.push_back (neg_infin);
+
+ transaction t (db->begin ());
+ assert (test_invalid_special_value (sv1, db));
+ assert (test_invalid_special_value (sv2, db));
+ t.commit ();
+ }
+ }
+ catch (const odb::exception& e)
+ {
+ cerr << e.what () << endl;
+ return 1;
+ }
+}
+
+bool
+test_invalid_special_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::special_value&)
+ {
+ }
+
+ return true;
+}
+
+bool
+test_out_of_range_value (object& x, unique_ptr<database>& db)
+{
+ try
+ {
+ db->persist (x);
+ return false;
+ }
+ catch (const odb::boost::date_time::value_out_of_range&)
+ {
+ }
+
+ return true;
+}
diff --git a/odb-tests/boost/sqlite/date-time/test.hxx b/odb-tests/boost/sqlite/date-time/test.hxx
new file mode 100644
index 0000000..924ce27
--- /dev/null
+++ b/odb-tests/boost/sqlite/date-time/test.hxx
@@ -0,0 +1,57 @@
+// file : boost/sqlite/date-time/test.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef TEST_HXX
+#define TEST_HXX
+
+#include <vector>
+
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <odb/core.hxx>
+
+#pragma db object
+struct object
+{
+ object ()
+ {
+ }
+
+ bool
+ operator== (const object& x) const
+ {
+ return
+ id == x.id &&
+ dates == x.dates &&
+ times == x.times &&
+ durations == x.durations &&
+ u_dates == x.u_dates &&
+ u_times == x.u_times &&
+ s_durations == x.s_durations;
+ }
+
+ #pragma db id auto
+ unsigned long id;
+
+ std::vector<boost::gregorian::date> dates;
+ std::vector<boost::posix_time::ptime> times;
+ std::vector<boost::posix_time::time_duration> durations;
+
+ // Dates as UNIX time.
+ //
+ #pragma db value_type("INTEGER")
+ std::vector<boost::gregorian::date> u_dates;
+
+ // Times as UNIX time.
+ //
+ #pragma db value_type("INTEGER")
+ std::vector<boost::posix_time::ptime> u_times;
+
+ // Durations as seconds.
+ //
+ #pragma db value_type("INTEGER")
+ std::vector<boost::posix_time::time_duration> s_durations;
+};
+
+#endif // TEST_HXX
diff --git a/odb-tests/boost/sqlite/date-time/testscript b/odb-tests/boost/sqlite/date-time/testscript
new file mode 100644
index 0000000..5805a80
--- /dev/null
+++ b/odb-tests/boost/sqlite/date-time/testscript
@@ -0,0 +1,9 @@
+# file : boost/sqlite/date-time/testscript
+# license : GNU GPL v2; see accompanying LICENSE file
+
+.include ../../../database-options.testscript
+.include ../../../sqlite.testscript
+
+: basics
+:
+$*