From 9e26a8a565aa4debe8b7eb86aa74ae39af9e7116 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 24 Nov 2010 16:37:09 +0200 Subject: Implement support for many-to-{one,many} inverse relationships --- common/inverse/driver.cxx | 179 +++++++++++++++++++++++++++++++++++++++------- common/inverse/test.hxx | 86 +++++++++++++++++++++- 2 files changed, 235 insertions(+), 30 deletions(-) diff --git a/common/inverse/driver.cxx b/common/inverse/driver.cxx index e3c8b22..e572be2 100644 --- a/common/inverse/driver.cxx +++ b/common/inverse/driver.cxx @@ -32,36 +32,78 @@ main (int argc, char* argv[]) // Naked pointer version. // { - obj1_ptr o1 (new obj1); + obj1_ptr o1_1 (new obj1); + obj1_ptr o1_2 (new obj1); obj2_ptr o2 (new obj2); obj3_ptr o3_1 (new obj3); obj3_ptr o3_2 (new obj3); + obj4_ptr o4_1 (new obj4); + obj4_ptr o4_2 (new obj4); + obj5_ptr o5_1 (new obj5); + obj5_ptr o5_2 (new obj5); + obj5_ptr o5_3 (new obj5); + obj5_ptr o5_4 (new obj5); - o1->id = "obj1"; - o1->o2 = o2; - o1->o3.insert (o3_1); - o1->o3.insert (o3_2); + o1_1->id = "obj1 1"; + o1_1->o2 = o2; + o1_1->o3.insert (o3_1); + o1_1->o3.insert (o3_2); + o1_1->o4 = o4_1; + o1_1->o5.insert (o5_1); + o1_1->o5.insert (o5_2); + + o1_2->id = "obj1 2"; + o1_2->o2 = 0; + o1_2->o3.clear (); + o1_2->o4 = o4_2; + o1_2->o5.insert (o5_3); + o1_2->o5.insert (o5_4); o2->str = "obj2"; - o2->o1 = o1; + o2->o1 = o1_1; o3_1->str = "obj3 1"; - o3_1->o1 = o1; + o3_1->o1 = o1_1; - o3_2->str = "obj3 3"; - o3_2->o1 = o1; + o3_2->str = "obj3 2"; + o3_2->o1 = o1_1; + + o4_1->str = "obj4 1"; + o4_1->o1.insert (o1_1); + + o4_2->str = "obj4 2"; + o4_2->o1.insert (o1_2); + + o5_1->str = "obj5 1"; + o5_1->o1.insert (o1_1); + + o5_2->str = "obj5 2"; + o5_2->o1.insert (o1_1); + + o5_3->str = "obj5 3"; + o5_3->o1.insert (o1_2); + + o5_4->str = "obj5 4"; + o5_4->o1.insert (o1_2); // persist // { transaction t (db->begin ()); - // obj2 and obj3 come first to get object id assigned. + // objN come before obj1 to get object id assigned. // + db->persist (o5_1); + db->persist (o5_2); + db->persist (o5_3); + db->persist (o5_4); + db->persist (o4_1); + db->persist (o4_2); db->persist (o3_1); db->persist (o3_2); db->persist (o2); - db->persist (o1); + db->persist (o1_1); + db->persist (o1_2); t.commit (); } @@ -74,59 +116,127 @@ main (int argc, char* argv[]) obj2_ptr x2 (db->load (o2->id)); obj3_ptr x3_1 (db->load (o3_1->id)); obj3_ptr x3_2 (db->load (o3_2->id)); + obj4_ptr x4_1 (db->load (o4_1->id)); + obj4_ptr x4_2 (db->load (o4_2->id)); + obj5_ptr x5_1 (db->load (o5_1->id)); + obj5_ptr x5_2 (db->load (o5_2->id)); + obj5_ptr x5_3 (db->load (o5_3->id)); + obj5_ptr x5_4 (db->load (o5_4->id)); t.commit (); assert (x2->str == o2->str); - assert (x2->o1->id == o1->id); + assert (x2->o1->id == o1_1->id); assert (x2->o1->o2 == x2); assert (x3_1->str == o3_1->str); assert (x3_2->str == o3_2->str); assert (x3_1->o1 == x3_2->o1); - assert (x3_1->o1->id == o1->id); + assert (x3_1->o1->id == o1_1->id); assert (x3_1->o1->o3.find (x3_1) != x3_1->o1->o3.end ()); assert (x3_1->o1->o3.find (x3_2) != x3_1->o1->o3.end ()); - delete x2->o1; + assert (x4_1->str == o4_1->str); + assert (x4_2->str == o4_2->str); + assert ((*x4_1->o1.begin ())->id == o1_1->id); + assert ((*x4_2->o1.begin ())->id == o1_2->id); + assert ((*x4_1->o1.begin ())->o4 == x4_1); + assert ((*x4_2->o1.begin ())->o4 == x4_2); + + assert (x5_1->str == o5_1->str); + assert (x5_2->str == o5_2->str); + assert ((*x5_1->o1.begin ())->id == o1_1->id); + assert ((*x5_2->o1.begin ())->id == o1_1->id); + assert ((*x5_3->o1.begin ())->id == o1_2->id); + assert ((*x5_4->o1.begin ())->id == o1_2->id); + assert ((*x5_1->o1.begin ())->o5.find (x5_1) != + (*x5_1->o1.begin ())->o5.end ()); + assert ((*x5_2->o1.begin ())->o5.find (x5_2) != + (*x5_2->o1.begin ())->o5.end ()); + assert ((*x5_3->o1.begin ())->o5.find (x5_3) != + (*x5_3->o1.begin ())->o5.end ()); + assert ((*x5_4->o1.begin ())->o5.find (x5_4) != + (*x5_4->o1.begin ())->o5.end ()); + + delete *x4_1->o1.begin (); + delete *x4_2->o1.begin (); } - delete o1; + delete o1_1; + delete o1_2; } // TR1 pointer version. // #ifdef HAVE_TR1_MEMORY { - tr1_obj1_ptr o1 (new tr1_obj1); + tr1_obj1_ptr o1_1 (new tr1_obj1); + tr1_obj1_ptr o1_2 (new tr1_obj1); tr1_obj2_ptr o2 (new tr1_obj2); tr1_obj3_ptr o3_1 (new tr1_obj3); tr1_obj3_ptr o3_2 (new tr1_obj3); + tr1_obj4_ptr o4 (new tr1_obj4); + tr1_obj5_ptr o5_1 (new tr1_obj5); + tr1_obj5_ptr o5_2 (new tr1_obj5); + tr1_obj5_ptr o5_3 (new tr1_obj5); + tr1_obj5_ptr o5_4 (new tr1_obj5); + + o1_1->id = "obj1 1"; + o1_1->o2 = o2; + o1_1->o3.push_back (o3_1); + o1_1->o3.push_back (o3_2); + o1_1->o4 = o4; + o1_1->o5.push_back (o5_1); + o1_1->o5.push_back (o5_2); - o1->id = "obj1"; - o1->o2 = o2; - o1->o3.push_back (o3_1); - o1->o3.push_back (o3_2); + o1_2->id = "obj1 2"; + o1_2->o2 = tr1_obj2_ptr (); + o1_2->o3.clear (); + //@@o1_2->o4 = o4; + o1_2->o5.push_back (o5_3); + o1_2->o5.push_back (o5_4); o2->str = "obj2"; - o2->o1 = o1; + o2->o1 = o1_1; o3_1->str = "obj3 1"; - o3_1->o1 = o1; + o3_1->o1 = o1_1; o3_2->str = "obj3 3"; - o3_2->o1 = o1; + o3_2->o1 = o1_1; + + o4->str = "obj4"; + o4->o1.push_back (o1_1); + //@@o4->o1.push_back (o1_2); + + o5_1->str = "obj5 1"; + o5_1->o1.push_back (o1_1); + + o5_2->str = "obj5 2"; + o5_2->o1.push_back (o1_1); + + o5_3->str = "obj5 3"; + o5_3->o1.push_back (o1_2); + + o5_4->str = "obj5 4"; + o5_4->o1.push_back (o1_2); // persist // { transaction t (db->begin ()); - // obj2 and obj3 come first to get object id assigned. + // objN come before obj1 to get object id assigned. // + db->persist (o5_1); + db->persist (o5_2); + db->persist (o5_3); + db->persist (o5_4); + db->persist (o4); db->persist (o3_1); db->persist (o3_2); db->persist (o2); - db->persist (o1); + db->persist (o1_1); + db->persist (o1_2); t.commit (); } @@ -139,18 +249,33 @@ main (int argc, char* argv[]) tr1_obj2_ptr x2 (db->load (o2->id)); tr1_obj3_ptr x3_1 (db->load (o3_1->id)); tr1_obj3_ptr x3_2 (db->load (o3_2->id)); + tr1_obj4_ptr x4 (db->load (o4->id)); + tr1_obj5_ptr x5_1 (db->load (o5_1->id)); + tr1_obj5_ptr x5_2 (db->load (o5_2->id)); + //@@ tr1_obj5_ptr x5_3 (db->load (o5_3->id)); + //@@ tr1_obj5_ptr x5_4 (db->load (o5_4->id)); t.commit (); assert (x2->str == o2->str); - assert (x2->o1.lock ()->id == o1->id); + assert (x2->o1.lock ()->id == o1_1->id); assert (x2->o1.lock ()->o2 == x2); assert (x3_1->str == o3_1->str); assert (x3_2->str == o3_2->str); assert (x3_1->o1.lock () == x3_2->o1.lock ()); - assert (x3_1->o1.lock ()->id == o1->id); + assert (x3_1->o1.lock ()->id == o1_1->id); assert (x3_1->o1.lock ()->o3[0] == x3_1); assert (x3_1->o1.lock ()->o3[1] == x3_2); + + assert (x4->str == o4->str); + /* + @@ + tr1_obj1_ptr t1 (x4->o1[0].lock ()), t2 (x4->o1[1].lock ()); + assert (t1->id == o1_1->id || t2->id == o1_1->id); + assert (t1->id == o1_2->id || t2->id == o1_2->id); + */ + + //@@ TODO: obj5 test } } #endif diff --git a/common/inverse/test.hxx b/common/inverse/test.hxx index df93e5d..e57cb78 100644 --- a/common/inverse/test.hxx +++ b/common/inverse/test.hxx @@ -17,17 +17,23 @@ struct obj1; struct obj2; struct obj3; +struct obj4; +struct obj5; typedef obj1* obj1_ptr; typedef obj2* obj2_ptr; typedef obj3* obj3_ptr; +typedef obj4* obj4_ptr; +typedef obj5* obj5_ptr; +typedef std::set obj1_ptr_set; typedef std::set obj3_ptr_set; +typedef std::set obj5_ptr_set; #pragma db object struct obj1 { - obj1 (): o2 (0) {} + obj1 (): o2 (0), o4 (0) {} ~obj1 (); #pragma db id @@ -37,6 +43,10 @@ struct obj1 #pragma db id_column("obj1_id") value_column("obj3_id") obj3_ptr_set o3; + + obj4_ptr o4; + + obj5_ptr_set o5; }; #pragma db object @@ -61,18 +71,49 @@ struct obj3 std::string str; - // one-to-many + // one(i)-to-many // #pragma db inverse (o3) obj1_ptr o1; }; +#pragma db object +struct obj4 +{ + #pragma db id auto + int id; + + std::string str; + + // many(i)-to-one + // + #pragma db inverse (o4) + obj1_ptr_set o1; +}; + +#pragma db object +struct obj5 +{ + #pragma db id auto + int id; + + std::string str; + + // many(i)-to-many + // + #pragma db inverse (o5) + obj1_ptr_set o1; +}; + inline obj1:: ~obj1 () { delete o2; for (obj3_ptr_set::iterator i (o3.begin ()); i != o3.end (); ++i) delete *i; + delete o4; + for (obj5_ptr_set::iterator i (o5.begin ()); i != o5.end (); ++i) + delete *i; } // TR1 version @@ -81,14 +122,20 @@ inline obj1:: struct tr1_obj1; struct tr1_obj2; struct tr1_obj3; +struct tr1_obj4; +struct tr1_obj5; typedef std::tr1::shared_ptr tr1_obj1_ptr; typedef std::tr1::shared_ptr tr1_obj2_ptr; typedef std::tr1::shared_ptr tr1_obj3_ptr; +typedef std::tr1::shared_ptr tr1_obj4_ptr; +typedef std::tr1::shared_ptr tr1_obj5_ptr; typedef std::tr1::weak_ptr tr1_obj1_wptr; +typedef std::vector tr1_obj1_wptr_vec; typedef std::vector tr1_obj3_ptr_vec; +typedef std::vector tr1_obj5_ptr_vec; #pragma db object pointer(tr1_obj1_ptr) struct tr1_obj1 @@ -100,6 +147,9 @@ struct tr1_obj1 #pragma db id_column("tr1_obj1_id") value_column("tr1_obj3_id") tr1_obj3_ptr_vec o3; + + tr1_obj4_ptr o4; + tr1_obj5_ptr_vec o5; }; #pragma db object pointer(tr1_obj2_ptr) @@ -110,6 +160,8 @@ struct tr1_obj2 std::string str; + // one(i)-to-one + // #pragma db inverse(o2) tr1_obj1_wptr o1; }; @@ -122,11 +174,39 @@ struct tr1_obj3 std::string str; - // one-to-many + // one(i)-to-many // #pragma db inverse (o3) tr1_obj1_wptr o1; }; + +#pragma db object pointer(tr1_obj4_ptr) +struct tr1_obj4 +{ + #pragma db id auto + int id; + + std::string str; + + // many(i)-to-one + // + #pragma db inverse (o4) + tr1_obj1_wptr_vec o1; +}; + +#pragma db object pointer(tr1_obj5_ptr) +struct tr1_obj5 +{ + #pragma db id auto + int id; + + std::string str; + + // many(i)-to-many + // + #pragma db inverse (o5) + tr1_obj1_wptr_vec o1; +}; #endif #endif // TEST_HXX -- cgit v1.1