diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-04 17:23:54 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-04 17:23:54 +0200 |
commit | 504fa38f3f71c345f41dfbb7e59b1d2f88308987 (patch) | |
tree | d4328b3cb9de151699232c9722e2f8899ac2f36b /common/view/olv/driver.cxx | |
parent | cbad49a571dfff9a046997b18776fd3cee6d7b51 (diff) |
Implement object loading views
See section 10.2 in the manual for details.
Diffstat (limited to 'common/view/olv/driver.cxx')
-rw-r--r-- | common/view/olv/driver.cxx | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/common/view/olv/driver.cxx b/common/view/olv/driver.cxx new file mode 100644 index 0000000..6ef2467 --- /dev/null +++ b/common/view/olv/driver.cxx @@ -0,0 +1,615 @@ +// file : common/view/olv/driver.cxx +// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +// Test object loading views. +// + +#include <memory> // std::auto_ptr +#include <cassert> +#include <iostream> +#include <typeinfo> + +#include <odb/session.hxx> +#include <odb/database.hxx> +#include <odb/transaction.hxx> + +#include <common/common.hxx> + +#include "test.hxx" +#include "test-odb.hxx" + +using namespace std; +using namespace odb::core; + +int +main (int argc, char* argv[]) +{ + try + { + auto_ptr<database> db (create_database (argc, argv)); + + // Test basic object loading functionality. + // + { + using namespace test1; + + { + object1 o1a (1, 123); + object2 o2 (1, "abc"); + + transaction t (db->begin ()); + db->persist (o1a); + db->persist (o2); + t.commit (); + } + + { + typedef odb::query<view1> query; + + transaction t (db->begin ()); + view1 v (db->query_value<view1> (query::object1::n == 123)); + assert (v.o2->s == "abc"); + t.commit (); + } + + { + transaction t (db->begin ()); + view2 v (db->query_value<view2> ()); + assert (v.o1->n == 123 && v.o2->s == "abc"); + t.commit (); + } + + { + transaction t (db->begin ()); + view3 v (db->query_value<view3> ()); + assert (v.o1->n == 123 && v.o2->s == "abc"); + t.commit (); + } + + { + transaction t (db->begin ()); + view4 v (db->query_value<view4> ()); + assert (v.s == "abc" && v.o2->s == "abc" && v.id == 1 && + v.o1->n == 123 && v.n == 123); + t.commit (); + } + + { + transaction t (db->begin ()); + view4 v (db->query_value<view4> ()); + assert (v.s == "abc" && v.o2->s == "abc" && v.id == 1 && + v.o1->n == 123 && v.n == 123); + t.commit (); + } + + { + typedef odb::query<view5> query; + + object1 o1b (123, 1); + + transaction t (db->begin ()); + db->persist (o1b); + view5 v (db->query_value<view5> (query::o1b::n == 1)); + assert (v.o1a->n == 123 && v.o2->s == "abc" && v.o1b->n == 1); + t.commit (); + } + } + + // Test loading of object pointers inside objects. + // + { + using namespace test2; + + shared_ptr<object1> o1 (new object1 (123)); + shared_ptr<object2> o2 (new object2 ("abc", o1)); + + { + + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + view1 v (db->query_value<view1> ()); + assert (v.o2->s == "abc" && v.o2->o1->n == 123); + t.commit (); + } + + { + // Check session interaction. + // + transaction t (db->begin ()); + session s; + shared_ptr<object2> o2a (db->load<object2> (o2->id)); + view1 v (db->query_value<view1> ()); + assert (v.o2 == o2a); + t.commit (); + } + + { + transaction t (db->begin ()); + session s; + view2 v (db->query_value<view2> ()); + assert (v.o1->n == 123 && v.o2->s == "abc" && v.o2->o1 == v.o1); + t.commit (); + } + + shared_ptr<object3> o3 (new object3 (o2)); + + { + transaction t (db->begin ()); + db->persist (o3); + t.commit (); + } + + { + transaction t (db->begin ()); + session s; + view3 v (db->query_value<view3> ()); + assert (v.o1->n == 123 && v.o3->o2->s == "abc" && + v.o3->o2->o1 == v.o1); + t.commit (); + } + + shared_ptr<object1> o1b (new object1 (234)); + shared_ptr<object2> o2b (new object2 ("bcd", o1b)); + shared_ptr<object4> o4 (new object4); + o4->o2.push_back (o2); + o4->o2.push_back (o2b); + + { + transaction t (db->begin ()); + db->persist (o1b); + db->persist (o2b); + db->persist (o4); + t.commit (); + } + + { + transaction t (db->begin ()); + view4 v (db->query_value<view4> ()); + assert (v.o4->o2[0]->s == "abc" && v.o4->o2[0]->o1->n == 123 && + v.o4->o2[1]->s == "bcd" && v.o4->o2[1]->o1->n == 234); + t.commit (); + } + + { + typedef odb::query<view5> query; + typedef odb::result<view5> result; + + transaction t (db->begin ()); + session s; + result r (db->query<view5> ("ORDER BY" + query::object1::id)); + result::iterator i (r.begin ()); + + assert (i != r.end ()); + { + view5 const& v (*i); + + assert (v.o4->o2[0]->s == "abc" && v.o4->o2[0]->o1->n == 123 && + v.o4->o2[1]->s == "bcd" && v.o4->o2[1]->o1->n == 234 && + v.o4->o2[0]->o1 == v.o1); + } + assert (++i != r.end ()); + { + view5 const& v (*i); + + assert (v.o4->o2[0]->s == "abc" && v.o4->o2[0]->o1->n == 123 && + v.o4->o2[1]->s == "bcd" && v.o4->o2[1]->o1->n == 234 && + v.o4->o2[1]->o1 == v.o1); + } + assert (++i == r.end ()); + t.commit (); + } + + shared_ptr<object5> o5 (new object5 (o1b, o2)); + + { + transaction t (db->begin ()); + db->persist (o5); + t.commit (); + } + + { + transaction t (db->begin ()); + view6 v (db->query_value<view6> ()); + assert (v.o1a->n == 123 && v.o1b->n == 234); + t.commit (); + } + } + + // Test JOINs for pointed-to objects, existing and automatically added. + // + { + using namespace test3; + + shared_ptr<object1> o1 (new object1 (123)); + shared_ptr<object2> o2 (new object2 ("abc")); + + o1->o2 = o2; + o2->o1 = o1; + + { + + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + view1a v (db->query_value<view1a> ()); + assert (v.o1->n == 123 && v.o1->o2.object_id () == o2->id); + t.commit (); + } + + { + transaction t (db->begin ()); + view1b v (db->query_value<view1b> ()); + assert (v.o1->n == 123 && v.o1->o2.object_id () == o2->id); + t.commit (); + } + + // Container case. + // + + shared_ptr<object3> o3 (new object3 (123)); + shared_ptr<object4> o4 (new object4 ("abc")); + + o3->o4 = o4; + o4->o3.push_back (o3); + + { + + transaction t (db->begin ()); + db->persist (o3); + db->persist (o4); + t.commit (); + } + + { + transaction t (db->begin ()); + view2a v (db->query_value<view2a> ()); + assert (v.o3->n == 123 && v.o3->o4.object_id () == o4->id); + t.commit (); + } + + { + transaction t (db->begin ()); + view2b v (db->query_value<view2b> ()); + assert (v.o3->n == 123 && v.o3->o4.object_id () == o4->id); + t.commit (); + } + } + + // Test by-value load. + // + { + using namespace test4; + + { + object1 o1 (1, 123); + object2 o2 (1, "abc", &o1); + + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + view1 v (db->query_value<view1> ()); + assert (v.o1.n == 123); + t.commit (); + } + + { + transaction t (db->begin ()); + view1a v (db->query_value<view1a> ()); + assert (!v.o1_null && v.o1.n == 123); + t.commit (); + } + + { + transaction t (db->begin ()); + view1b v (db->query_value<view1b> ()); + assert (/*v.o1_p == &v.o1 && */ v.o1.n == 123); // Copy ctor. + t.commit (); + } + + { + typedef odb::result<view1c> result; + + transaction t (db->begin ()); + result r (db->query<view1c> ()); + result::iterator i (r.begin ()); + assert (i != r.end ()); + + object1 o1; + view1c v (o1); + i.load (v); + + assert (v.o1_p == &o1 && o1.n == 123); + + assert (++i == r.end ()); + t.commit (); + } + + { + transaction t (db->begin ()); + session s; + view2 v (db->query_value<view2> ()); + assert (v.o1.n == 123 && v.o2.s == "abc" && v.o2.o1 == &v.o1); + t.commit (); + } + + object1 o1b (2, 234); + + { + transaction t (db->begin ()); + db->persist (o1b); + t.commit (); + } + + { + typedef odb::query<view2a> query; + + transaction t (db->begin ()); + session s; + view2a v (db->query_value<view2a> (query::object1::id == 2)); + assert (v.o1.n == 234 && v.o2_null); + t.commit (); + } + + shared_ptr<object3> o3 (new object3 (1, 123)); + + { + transaction t (db->begin ()); + db->persist (o3); + t.commit (); + } + + { + transaction t (db->begin ()); + { + view3 v (db->query_value<view3> ()); + assert (v.o3_p == &v.o3 && v.o3.n == 123); // Load into value. + } + session s; // Load into cache. + shared_ptr<object3> o3a (db->load<object3> (o3->id)); + { + view3 v (db->query_value<view3> ()); + assert (v.o3_p == o3a.get ()); // Load from cache. + } + t.commit (); + } + } + + // Test NULL object pointers. + // + { + using namespace test5; + + shared_ptr<object1> o1a (new object1 (123)); + shared_ptr<object1> o1b (new object1 (234)); + shared_ptr<object2> o2 (new object2 ("abc", o1a)); + + { + transaction t (db->begin ()); + db->persist (o1a); + db->persist (o1b); + db->persist (o2); + t.commit (); + } + + { + typedef odb::query<view1> query; + typedef odb::result<view1> result; + + transaction t (db->begin ()); + session s; + result r (db->query<view1> ("ORDER BY" + query::object1::id)); + result::iterator i (r.begin ()); + + assert (i != r.end ()); + { + view1 const& v (*i); + assert (v.o1->n == 123 && v.o2->s == "abc" && v.o2->o1 == v.o1); + } + assert (++i != r.end ()); + { + view1 const& v (*i); + assert (v.o1->n == 234 && !v.o2); + } + assert (++i == r.end ()); + t.commit (); + } + + shared_ptr<object3> o3a (new object3 (make_pair (1, 1), 123)); + shared_ptr<object3> o3b (new object3 (make_pair (2, 2), 234)); + shared_ptr<object4> o4 (new object4 ("abc", o3a)); + + { + transaction t (db->begin ()); + db->persist (o3a); + db->persist (o3b); + db->persist (o4); + t.commit (); + } + + { + typedef odb::query<view2> query; + typedef odb::result<view2> result; + + transaction t (db->begin ()); + session s; + result r (db->query<view2> ("ORDER BY" + query::object3::n)); + result::iterator i (r.begin ()); + + assert (i != r.end ()); + { + view2 const& v (*i); + assert (v.o3->n == 123 && v.o4->s == "abc" && v.o4->o3 == v.o3); + } + assert (++i != r.end ()); + { + view2 const& v (*i); + assert (v.o3->n == 234 && !v.o4); + } + assert (++i == r.end ()); + t.commit (); + } + } + + // Test interaction with sections. + // + { + using namespace test6; + + shared_ptr<object1> o1 (new object1 (123)); + shared_ptr<object2> o2 (new object2 ("abc", o1)); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + view1 v (db->query_value<view1> ()); + assert (v.o1->n == 123 && v.o2->s == "abc" && + !v.o2->r.loaded () && !v.o2->o1); + t.commit (); + } + } + + // Test explicit conversion to smart pointer member. + // + { + using namespace test7; + + object1 o1 (123); + object2 o2 ("abc", &o1); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + session s; + view1 v (db->query_value<view1> ()); + assert (v.o1->n == 123 && v.o2->s == "abc" && v.o2->o1 == v.o1.get ()); + t.commit (); + } + } + + // Test loading objects without id. + // + { + using namespace test8; + + object1 o1 (123); + object2 o2 ("abc", &o1); + + { + transaction t (db->begin ()); + db->persist (o1); + db->persist (o2); + t.commit (); + } + + { + transaction t (db->begin ()); + session s; + view1 v (db->query_value<view1> ()); + assert (v.o1->n == 123 && v.o2->s == "abc" && v.o2->o1 == v.o1.get ()); + t.commit (); + } + } + + // Test loading polymorphic objects. + // + { + using namespace test9; + + root r (1); + base b (2, "a"); + derived d (3, "b", true); + + { + transaction t (db->begin ()); + db->persist (r); + db->persist (b); + db->persist (d); + t.commit (); + } + + { + transaction t (db->begin ()); + + // Load via root. + // + { + view1r r (db->query_value<view1r> (query<view1r>::n == 1)); + assert (r.n == 1 && r.o->n == 1 && typeid (*r.o) == typeid (root)); + } + + { + view1r r (db->query_value<view1r> (query<view1r>::n == 2)); + assert (r.n == 2 && r.o->n == 2 && typeid (*r.o) == typeid (base)); + base& b (dynamic_cast<base&> (*r.o)); + assert (b.s == "a"); + } + + { + view1r r (db->query_value<view1r> (query<view1r>::n == 3)); + assert (r.n == 3 && r.o->n == 3 && typeid (*r.o) == typeid (derived)); + derived& d (dynamic_cast<derived&> (*r.o)); + assert (d.s == "b" && d.b); + } + + // Load via base. + // + { + view1b r (db->query_value<view1b> (query<view1b>::n == 2)); + assert (r.s == "a" && r.n == 2 && r.o->n == 2 && b.s == "a"); + } + + { + view1b r (db->query_value<view1b> (query<view1b>::n == 3)); + assert (r.s == "b" && r.n == 3 && r.o->n == 3 && + typeid (*r.o) == typeid (derived)); + derived& d (dynamic_cast<derived&> (*r.o)); + assert (d.s == "b" && d.b); + } + + // Load via derived. + // + { + view1d r (db->query_value<view1d> ()); + assert (r.s == "b" && r.n == 3 && + r.o->n == 3 && r.o->s == "b" && r.o->b); + } + + t.commit (); + } + } + } + catch (const odb::exception& e) + { + cerr << e.what () << endl; + return 1; + } +} |