diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-06 08:57:30 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-06 08:57:30 +0200 |
commit | a44bbf24decdaee9bd8c716dc6843b4b4c6c7ec5 (patch) | |
tree | 664bd5a34d066573fd94b7dbd829bf116d324c19 | |
parent | 55a308d14dc12594c365767d738f71893248f159 (diff) |
Implement join types support in views
-rw-r--r-- | common/view/basics/driver.cxx | 144 | ||||
-rw-r--r-- | common/view/basics/test.hxx | 104 |
2 files changed, 248 insertions, 0 deletions
diff --git a/common/view/basics/driver.cxx b/common/view/basics/driver.cxx index 01ae0ab..557efda 100644 --- a/common/view/basics/driver.cxx +++ b/common/view/basics/driver.cxx @@ -682,6 +682,150 @@ main (int argc, char* argv[]) assert (size (db->query<view14> ()) == 2); t.commit (); } + + // Test join types. + // + { + using namespace test2; + + { + obj1 o11 (1, 1); + obj1 o12 (2, 2); + + obj2 o21 (1, 1); + obj2 o22 (2, 1); + obj2 o23 (3, 3); + + transaction t (db->begin ()); + db->persist (o11); + db->persist (o12); + db->persist (o21); + db->persist (o22); + db->persist (o23); + t.commit (); + } + + { + typedef odb::query<vleft> query; + typedef odb::result<vleft> result; + + transaction t (db->begin ()); + result r (db->query<vleft> ( + "ORDER BY" + query::o1::id1 + "," + query::o2::id2)); + result::iterator i (r.begin ()); + assert ( i != r.end () && i->id1 == 1 && *i->id2 == 1); + assert (++i != r.end () && i->id1 == 1 && *i->id2 == 2); + assert (++i != r.end () && i->id1 == 2 && i->id2.null ()); + assert (++i == r.end ()); + t.commit (); + } + +#if !defined(DATABASE_SQLITE) + { + typedef odb::query<vright> query; + typedef odb::result<vright> result; + + transaction t (db->begin ()); + result r (db->query<vright> ( + "ORDER BY" + query::o1::id1 + "," + query::o2::id2)); + result::iterator i (r.begin ()); + assert ( i != r.end () && i->id1 == 1 && *i->id2 == 1); + assert (++i != r.end () && i->id1 == 1 && *i->id2 == 2); + assert (++i != r.end () && i->id1 == 2 && i->id2.null ()); + assert (++i == r.end ()); + t.commit (); + } +#endif + +#if !defined(DATABASE_MYSQL) && !defined(DATABASE_SQLITE) + { + typedef odb::query<vfull> query; + typedef odb::result<vfull> result; + + transaction t (db->begin ()); + result r (db->query<vfull> ( + "ORDER BY" + query::o1::id1 + "," + query::o2::id2)); + result::iterator i (r.begin ()); + + // SQL Server orders NULL values first. Got to be different. + // +#ifdef DATABASE_MSSQL + assert ( i != r.end () && i->id1.null () && *i->id2 == 3); + assert (++i != r.end () && *i->id1 == 1 && *i->id2 == 1); + assert (++i != r.end () && *i->id1 == 1 && *i->id2 == 2); + assert (++i != r.end () && *i->id1 == 2 && i->id2.null ()); +#else + assert ( i != r.end () && *i->id1 == 1 && *i->id2 == 1); + assert (++i != r.end () && *i->id1 == 1 && *i->id2 == 2); + assert (++i != r.end () && *i->id1 == 2 && i->id2.null ()); + assert (++i != r.end () && i->id1.null () && *i->id2 == 3); +#endif + assert (++i == r.end ()); + t.commit (); + } +#endif + + { + typedef odb::query<vinner> query; + typedef odb::result<vinner> result; + + transaction t (db->begin ()); + result r (db->query<vinner> ( + "ORDER BY" + query::o1::id1 + "," + query::o2::id2)); + result::iterator i (r.begin ()); + assert ( i != r.end () && i->id1 == 1 && i->id2 == 1); + assert (++i != r.end () && i->id1 == 1 && i->id2 == 2); + assert (++i == r.end ()); + t.commit (); + } + + { + typedef odb::query<vcross> query; + typedef odb::result<vcross> result; + + transaction t (db->begin ()); + result r (db->query<vcross> ( + "ORDER BY" + query::o1::id1 + "," + query::o2::id2)); + result::iterator i (r.begin ()); + assert ( i != r.end () && i->id1 == 1 && i->id2 == 1); + assert (++i != r.end () && i->id1 == 1 && i->id2 == 2); + assert (++i != r.end () && i->id1 == 1 && i->id2 == 3); + assert (++i != r.end () && i->id1 == 2 && i->id2 == 1); + assert (++i != r.end () && i->id1 == 2 && i->id2 == 2); + assert (++i != r.end () && i->id1 == 2 && i->id2 == 3); + assert (++i == r.end ()); + t.commit (); + } + + // Inner JOIN via relationship/container. + // + { + obj3 o31 (1, 1); + obj3 o32 (2, 2); + + obj4 o41 (1, 1); + obj4 o42 (2, 2); + o42.o3.push_back (&o32); + + transaction t (db->begin ()); + db->persist (o31); + db->persist (o32); + db->persist (o41); + db->persist (o42); + t.commit (); + } + + { + typedef odb::result<vrel> result; + + transaction t (db->begin ()); + result r (db->query<vrel> ()); + result::iterator i (r.begin ()); + assert ( i != r.end () && i->id4 == 2); + assert (++i == r.end ()); + t.commit (); + } + } } catch (const odb::exception& e) { diff --git a/common/view/basics/test.hxx b/common/view/basics/test.hxx index e9d61a5..0a2243d 100644 --- a/common/view/basics/test.hxx +++ b/common/view/basics/test.hxx @@ -5,6 +5,8 @@ #ifndef TEST_HXX #define TEST_HXX +#include <common/config.hxx> // DATABASE_* + #include <string> #include <vector> #include <cstddef> // std::size_t @@ -510,4 +512,106 @@ struct view14 std::string name; }; +// Test join types. +// +#pragma db namespace table("t2_") +namespace test2 +{ + #pragma db object + struct obj1 + { + obj1 (int id = 0, int n_ = 0): id1 (id), n (n_) {} + + #pragma db id + int id1; + + int n; + }; + + #pragma db object no_id + struct obj2 + { + obj2 (int id = 0, int n_ = 0): id2 (id), n (n_) {} + + #pragma db id + int id2; + + int n; + }; + + #pragma db view object(obj1 = o1) object(obj2 = o2 left: o1::n == o2::n) + struct vleft + { + int id1; + odb::nullable<int> id2; + }; + +#if !defined(DATABASE_SQLITE) + + #pragma db view object(obj2 = o2) object(obj1 = o1 right: o2::n == o1::n) + struct vright + { + int id1; + odb::nullable<int> id2; + }; + +#endif + +#if !defined(DATABASE_MYSQL) && !defined(DATABASE_SQLITE) + + #pragma db view object(obj1 = o1) object(obj2 = o2 full: o1::n == o2::n) + struct vfull + { + odb::nullable<int> id1; + odb::nullable<int> id2; + }; + +#endif + + #pragma db view object(obj1 = o1) object(obj2 = o2 inner: o1::n == o2::n) + struct vinner + { + int id1; + int id2; + }; + + #pragma db view object(obj1 = o1) object(obj2 = o2 cross) + struct vcross + { + int id1; + int id2; + }; + + // Inner JOIN via relationship/container. + // + #pragma db object + struct obj3 + { + obj3 (int id = 0, int n_ = 0): id3 (id), n (n_) {} + + #pragma db id + int id3; + + int n; + }; + + #pragma db object no_id + struct obj4 + { + obj4 (int id = 0, int n_ = 0): id4 (id), n (n_) {} + + #pragma db id + int id4; + + int n; + std::vector<obj3*> o3; + }; + + #pragma db view object(obj4) object(obj3 inner) + struct vrel + { + int id4; + }; +} + #endif // TEST_HXX |