aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-02-06 08:57:30 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-02-06 08:57:30 +0200
commita44bbf24decdaee9bd8c716dc6843b4b4c6c7ec5 (patch)
tree664bd5a34d066573fd94b7dbd829bf116d324c19
parent55a308d14dc12594c365767d738f71893248f159 (diff)
Implement join types support in views
-rw-r--r--common/view/basics/driver.cxx144
-rw-r--r--common/view/basics/test.hxx104
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