From edfd1193d15696c7a2e54573776b9121d6167e83 Mon Sep 17 00:00:00 2001
From: Boris Kolpackov <boris@codesynthesis.com>
Date: Fri, 27 Apr 2012 13:32:46 +0200
Subject: Support for NULL value semantics for composite values

---
 common/wrapper/driver.cxx | 74 +++++++++++++++++++++++++++++++++++++++++++++++
 common/wrapper/test.hxx   | 54 ++++++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+)

diff --git a/common/wrapper/driver.cxx b/common/wrapper/driver.cxx
index 4f78a1b..d8985fa 100644
--- a/common/wrapper/driver.cxx
+++ b/common/wrapper/driver.cxx
@@ -128,6 +128,80 @@ main (int argc, char* argv[])
         assert (o->c == co.c);
       }
     }
+
+    // Test 5: composite NULL values.
+    //
+    {
+      using namespace test5;
+
+      using test5::object; //@@ tmp
+
+      object o1, o2;
+
+      o1.v.push_back (nullable<comp> ());
+
+      o2.p.reset (new comp (1, "a"));
+      o2.n = comp (2, "b");
+      o2.v.push_back (comp (3, "c"));
+
+      // Persist.
+      //
+      {
+        transaction t (db->begin ());
+        db->persist (o1);
+        db->persist (o2);
+        t.commit ();
+      }
+
+      // Load.
+      //
+      {
+        transaction t (db->begin ());
+        auto_ptr<object> p1 (db->load<object> (o1.id));
+        auto_ptr<object> p2 (db->load<object> (o2.id));
+        t.commit ();
+
+        assert (p1->p.get () == 0);
+        assert (!p1->n);
+        assert (!p1->v[0]);
+
+        assert (p2->p.get () != 0 && *p2->p == *o2.p);
+        assert (p2->n && *p2->n == *o2.n);
+        assert (p2->v[0] && *p2->v[0] == *o2.v[0]);
+      }
+
+      // Update.
+      //
+      {
+        o1.p.reset (new comp (1, "a"));
+        o1.n = comp (2, "b");
+        o1.v[0] = comp (3, "c");
+
+        o2.p.reset ();
+        o2.n.reset ();
+        o2.v[0].reset ();
+
+        transaction t (db->begin ());
+        db->update (o1);
+        db->update (o2);
+        t.commit ();
+      }
+
+      {
+        transaction t (db->begin ());
+        auto_ptr<object> p1 (db->load<object> (o1.id));
+        auto_ptr<object> p2 (db->load<object> (o2.id));
+        t.commit ();
+
+        assert (p1->p.get () != 0 && *p1->p == *o1.p);
+        assert (p1->n && *p1->n == *o1.n);
+        assert (p1->v[0] && *p1->v[0] == *o1.v[0]);
+
+        assert (p2->p.get () == 0);
+        assert (!p2->n);
+        assert (!p2->v[0]);
+      }
+    }
   }
   catch (const odb::exception& e)
   {
diff --git a/common/wrapper/test.hxx b/common/wrapper/test.hxx
index ccf32b3..399073d 100644
--- a/common/wrapper/test.hxx
+++ b/common/wrapper/test.hxx
@@ -176,4 +176,58 @@ struct cont_object
   cont_comp c;    // Wrapped container in comp value.
 };
 
+// Test composite NULL values.
+//
+#pragma db namespace table("t5_")
+namespace test5
+{
+  #pragma db value
+  struct base
+  {
+    base () {}
+    base (int n): num (n) {}
+
+    int num;
+  };
+
+  inline bool
+  operator== (const base& x, const base& y)
+  {
+    return x.num == y.num;
+  }
+
+  #pragma db value
+  struct comp: base
+  {
+    comp () {}
+    comp (int n, const std::string s): base (n), str (s), extra (n + 1) {}
+
+    std::string str;
+    base extra;
+
+    odb::nullable<int> always_null;
+  };
+
+  inline bool
+  operator== (const comp& x, const comp& y)
+  {
+    return static_cast<const base&> (x) == y &&
+      x.str == y.str && x.extra == y.extra;
+  }
+
+  #pragma db object
+  struct object
+  {
+    #pragma db id auto
+    unsigned long id;
+
+    #pragma db null
+    std::auto_ptr<comp> p;
+
+    odb::nullable<comp> n;
+
+    std::vector< odb::nullable<comp> > v;
+  };
+}
+
 #endif // TEST_HXX
-- 
cgit v1.1