From 458296a902060900487f80219a8762142bb7800e Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Thu, 18 Aug 2011 11:38:40 +0200
Subject: Fix custom recursive loading in post_load callback

Before we called the callback while holding the statements locked. As a
result, if the callback tried to load another object of this type, it
failed. Now we unlock the statements (since we have completely loaded
the object from ODB's point of view) and then call the callback. The
callback test has been updated to test this situation.
---
 common/callback/driver.cxx | 29 +++++++++++++++++++++++++----
 common/callback/test.hxx   | 17 +++++++++++++++--
 common/callback/test.std   | 10 ++++++++++
 3 files changed, 50 insertions(+), 6 deletions(-)

(limited to 'common')

diff --git a/common/callback/driver.cxx b/common/callback/driver.cxx
index 4179168..fc67aac 100644
--- a/common/callback/driver.cxx
+++ b/common/callback/driver.cxx
@@ -34,9 +34,17 @@ const char* events[] =
 };
 
 void object::
-db_callback (callback_event e, database&)
+db_callback (callback_event e, database& db)
 {
   cout << "  " << events[e] << " " << id_ << endl;
+
+  // Test custom recursive loading.
+  //
+  if (e == callback_event::post_load && ref != 0)
+  {
+    robj = db.load<object> (ref);
+    cout << "    " << id_ << ' ' << ref << ' ' << robj->id_ << endl;
+  }
 }
 
 void object::
@@ -132,23 +140,36 @@ main (int argc, char* argv[])
       {
         object o1 (1, 1);
         object o2 (2, 2);
-        object o3 (3, 2);
+        object o3 (3, 3);
+        object o4 (4, 4);
 
         o1.pobj = &o2;
+        o1.ref = 4;
+
         o2.pobj = &o3;
+        o2.ref = 4;
 
         transaction t (db->begin ());
         db->persist (o1);
         db->persist (o2);
         db->persist (o3);
+        db->persist (o4);
         t.commit ();
       }
 
       {
         transaction t (db->begin ());
         auto_ptr<object> o1 (db->load<object> (1));
-        delete o1->pobj->pobj;
-        delete o1->pobj;
+        object* o2 (o1->pobj);
+
+        cout << o1->id_ << ' ' << o1->ref << ' ' << o1->robj->id_ << endl;
+        cout << o2->id_ << ' ' << o2->ref << ' ' << o2->robj->id_ << endl;
+
+        delete o1->robj;
+        delete o2->robj;
+
+        delete o2->pobj;
+        delete o2;
         t.commit ();
       }
     }
diff --git a/common/callback/test.hxx b/common/callback/test.hxx
index 274e2b5..058a327 100644
--- a/common/callback/test.hxx
+++ b/common/callback/test.hxx
@@ -12,8 +12,15 @@
 #pragma db object callback(db_callback)
 struct object
 {
-  object (unsigned long id, unsigned long d): id_ (id), data (d), pobj (0) {}
-  object (): id_ (0) {};
+  object (unsigned long id, unsigned long d)
+      : id_ (id), data (d), pobj (0), robj (0), ref (0)
+  {
+  }
+
+  object ()
+      : id_ (0), pobj (0), robj (0)
+  {
+  }
 
   #pragma db id
   unsigned long id_;
@@ -22,6 +29,12 @@ struct object
 
   object* pobj;
 
+  // Test custom recursive loading.
+  //
+  #pragma db transient
+  object* robj;
+  unsigned long ref; // Unless 0, reference to another object.
+
   void
   db_callback (odb::callback_event, odb::database&);
 
diff --git a/common/callback/test.std b/common/callback/test.std
index 05ae286..c1afa36 100644
--- a/common/callback/test.std
+++ b/common/callback/test.std
@@ -43,10 +43,20 @@ delayed load
   post_persist 2
   pre_persist 3
   post_persist 3
+  pre_persist 4
+  post_persist 4
   pre_load 0
   pre_load 0
   pre_load 0
   post_load 3
   post_load 2
+  pre_load 0
+  post_load 4
+    2 4 4
   post_load 1
+  pre_load 0
+  post_load 4
+    1 4 4
+1 4 4
+2 4 4
 ***
-- 
cgit v1.1