From b92d2fd35052373476fd392238695fe145ef49c2 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Tue, 16 Jun 2015 08:19:25 +0200
Subject: Implement support for nested members in inverse pragma

---
 common/inverse/driver.cxx | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 common/inverse/test.hxx   | 88 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 178 insertions(+)

(limited to 'common/inverse')

diff --git a/common/inverse/driver.cxx b/common/inverse/driver.cxx
index ed02509..08fd78c 100644
--- a/common/inverse/driver.cxx
+++ b/common/inverse/driver.cxx
@@ -404,6 +404,96 @@ main (int argc, char* argv[])
         }
       }
     }
+
+    // Test inverse with nested data members.
+    //
+    {
+      using namespace test4;
+
+      {
+        obj1 o1;
+        o1.o2 = new obj2;
+
+        {
+          transaction t (db->begin ());
+
+          o1.o2->id.i = db->persist (o1);
+          o1.o2->id.j = 123;
+          db->persist (o1.o2);
+
+          t.commit ();
+        }
+
+        {
+          transaction t (db->begin ());
+
+          auto_ptr<obj1> p (db->load<obj1> (o1.id));
+          assert (p->o2->id.i == o1.o2->id.i && p->o2->id.j == o1.o2->id.j);
+
+          t.commit ();
+        }
+
+        {
+          typedef odb::query<obj1> query;
+
+          transaction t (db->begin ());
+
+          auto_ptr<obj1> p (db->query_one<obj1> (
+                              query::o2->id.i == o1.o2->id.i &&
+                              query::o2->id.j == o1.o2->id.j));
+          assert (p->o2->id.i == o1.o2->id.i && p->o2->id.j == o1.o2->id.j);
+
+          t.commit ();
+        }
+      }
+
+      {
+        obj3 o3;
+        o3.o4.push_back (new obj4);
+        o3.o4.push_back (new obj4);
+
+        {
+          transaction t (db->begin ());
+
+          o3.o4[0]->id.i = o3.o4[1]->id.i = db->persist (o3);
+          o3.o4[0]->id.j = 123;
+          o3.o4[1]->id.j = 234;
+          db->persist (o3.o4[0]);
+          db->persist (o3.o4[1]);
+
+          t.commit ();
+        }
+
+        {
+          transaction t (db->begin ());
+
+          auto_ptr<obj3> p (db->load<obj3> (o3.id));
+          assert (p->o4[0]->id.i == o3.o4[0]->id.i &&
+                  p->o4[0]->id.j == o3.o4[0]->id.j);
+
+          assert (p->o4[1]->id.i == o3.o4[1]->id.i &&
+                  p->o4[1]->id.j == o3.o4[1]->id.j);
+
+          t.commit ();
+        }
+
+        {
+          typedef odb::query<obj3> query;
+
+          transaction t (db->begin ());
+
+          auto_ptr<obj3> p (db->query_one<obj3> (query::id == o3.id));
+
+          assert (p->o4[0]->id.i == o3.o4[0]->id.i &&
+                  p->o4[0]->id.j == o3.o4[0]->id.j);
+
+          assert (p->o4[1]->id.i == o3.o4[1]->id.i &&
+                  p->o4[1]->id.j == o3.o4[1]->id.j);
+
+          t.commit ();
+        }
+      }
+    }
   }
   catch (const odb::exception& e)
   {
diff --git a/common/inverse/test.hxx b/common/inverse/test.hxx
index 52a525d..6dfedda 100644
--- a/common/inverse/test.hxx
+++ b/common/inverse/test.hxx
@@ -311,4 +311,92 @@ namespace test3
   }
 };
 
+// Test inverse with nested data members.
+//
+#pragma db namespace table("t4_")
+namespace test4
+{
+  // Inverse pointer.
+  //
+  struct obj1;
+  struct obj2;
+
+  #pragma db value
+  struct obj2_id
+  {
+    #pragma db points_to(obj1)
+    int i;
+    int j;
+  };
+
+  inline bool
+  operator< (obj2_id x, obj2_id y)
+  {return x.i < y.i || (x.i == y.i && x.j < y.j);}
+
+  #pragma db object
+  struct obj1
+  {
+    #pragma db id auto
+    int id;
+
+    #pragma db inverse(id.i)
+    obj2* o2;
+
+    obj1 (): o2 (0) {}
+    ~obj1 ();
+  };
+
+  #pragma db object
+  struct obj2
+  {
+    #pragma db id
+    obj2_id id;
+  };
+
+  inline obj1::
+  ~obj1 () {delete o2;}
+
+  // Inverse container of pointers.
+  //
+  struct obj3;
+  struct obj4;
+
+  #pragma db value
+  struct obj4_id
+  {
+    #pragma db points_to(obj3)
+    int i;
+    int j;
+  };
+
+  inline bool
+  operator< (obj4_id x, obj4_id y)
+  {return x.i < y.i || (x.i == y.i && x.j < y.j);}
+
+  #pragma db object
+  struct obj3
+  {
+    #pragma db id auto
+    int id;
+
+    #pragma db inverse(id.i)
+    std::vector<obj4*> o4;
+
+    ~obj3 ();
+  };
+
+  #pragma db object
+  struct obj4
+  {
+    #pragma db id
+    obj4_id id;
+  };
+
+  inline obj3::
+  ~obj3 ()
+  {
+    for (std::vector<obj4*>::iterator i (o4.begin ()); i != o4.end (); ++i)
+      delete *i;
+  }
+};
 #endif // TEST_HXX
-- 
cgit v1.1