aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-04-27 13:32:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-04-27 13:32:45 +0200
commitf8b3ee6d42f5112c4e66a07cc7fdba43ce66aacd (patch)
tree2f3d877c7174e345514fe01cf9e462c1cb18b7ac /odb
parent15b1a95942518c84f8161c59820ea5d0e49a4e54 (diff)
Support for NULL value semantics for composite values
Diffstat (limited to 'odb')
-rw-r--r--odb/relational/source.hxx61
-rw-r--r--odb/validator.cxx54
2 files changed, 95 insertions, 20 deletions
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 594274a..2f2a61e 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -1170,26 +1170,41 @@ namespace relational
member = "o." + name;
}
- os << "{";
-
- if (discriminator (mi.m))
- os << "const info_type& di (map->find (typeid (o)));"
- << endl;
-
bool comp (composite (mi.t));
// If this is a wrapped composite value, then we need to "unwrap"
- // it. For simple values this is taken care of by the value_traits
+ // it. If this is a NULL wrapper, then we also need to handle that.
+ // For simple values this is taken care of by the value_traits
// specializations.
//
if (mi.wrapper != 0 && comp)
{
- // Here we need the wrapper type, not the wrapped type.
+ // The wrapper type, not the wrapped type.
//
- member = "wrapper_traits< " + mi.fq_type (false) + " >::" +
- "get_ref (" + member + ")";
+ string const& wt (mi.fq_type (false));
+
+ // If this is a NULL wrapper and the member can be NULL, then
+ // we need to handle the NULL value.
+ //
+ if (null (mi.m, key_prefix_) &&
+ mi.wrapper->template get<bool> ("wrapper-null-handler"))
+ {
+ os << "if (wrapper_traits< " + wt + " >::get_null (" <<
+ member << "))" << endl
+ << "composite_value_traits< " + mi.fq_type () + " >::" <<
+ "set_null (i." << mi.var << "value, sk);"
+ << "else";
+ }
+
+ member = "wrapper_traits< " + wt + " >::get_ref (" + member + ")";
}
+ os << "{";
+
+ if (discriminator (mi.m))
+ os << "const info_type& di (map->find (typeid (o)));"
+ << endl;
+
if (mi.ptr != 0)
{
// When handling a pointer, mi.t is the id type of the referenced
@@ -1431,16 +1446,30 @@ namespace relational
bool comp (composite (mi.t));
- // If this is a wrapped composite value, then we need to
- // "unwrap" it. For simple values this is taken care of
- // by the value_traits specializations.
+ // If this is a wrapped composite value, then we need to "unwrap" it.
+ // If this is a NULL wrapper, then we also need to handle that. For
+ // simple values this is taken care of by the value_traits
+ // specializations.
//
if (mi.wrapper != 0 && comp)
{
- // Here we need the wrapper type, not the wrapped type.
+ // The wrapper type, not the wrapped type.
+ //
+ string const& wt (mi.fq_type (false));
+
+ // If this is a NULL wrapper and the member can be NULL, then
+ // we need to handle the NULL value.
//
- member = "wrapper_traits< " + mi.fq_type (false) + " >::" +
- "set_ref (\n" + member + ")";
+ if (null (mi.m, key_prefix_) &&
+ mi.wrapper->template get<bool> ("wrapper-null-handler"))
+ {
+ os << "if (composite_value_traits< " + mi.fq_type () + " >::" <<
+ "get_null (i." << mi.var << "value))" << endl
+ << "wrapper_traits< " + wt + " >::set_null (" << member + ");"
+ << "else" << endl;
+ }
+
+ member = "wrapper_traits< " + wt + " >::set_ref (" + member + ")";
}
if (mi.ptr != 0)
diff --git a/odb/validator.cxx b/odb/validator.cxx
index eac5086..b0a6492 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -42,9 +42,9 @@ namespace
// Pass 1.
//
- struct data_member: traversal::data_member, context
+ struct data_member1: traversal::data_member, context
{
- data_member (bool& valid)
+ data_member1 (bool& valid)
: valid_ (valid)
{
}
@@ -776,7 +776,7 @@ namespace
bool& valid_;
value_type& vt_;
- data_member member_;
+ data_member1 member_;
traversal::names names_;
};
@@ -804,6 +804,41 @@ namespace
// Pass 2.
//
+ struct data_member2: traversal::data_member, context
+ {
+ data_member2 (bool& valid)
+ : valid_ (valid)
+ {
+ }
+
+ virtual void
+ traverse (type& m)
+ {
+ if (transient (m))
+ return;
+
+ if (null (m))
+ {
+ if (semantics::class_* c = composite_wrapper (utype (m)))
+ {
+ if (has_a (*c, test_container))
+ {
+ os << m.file () << ":" << m.line () << ":" << m.column () << ":"
+ << " error: composite member containing containers cannot "
+ << "be null" << endl;
+
+ os << c->file () << ":" << c->line () << ":" << c->column () << ":"
+ << " info: composite value type is defined here" << endl;
+
+ valid_ = false;
+ }
+ }
+ }
+ }
+
+ bool& valid_;
+ };
+
struct object_no_id_members: object_members_base
{
object_no_id_members (bool& valid)
@@ -985,10 +1020,13 @@ namespace
{
class2 (bool& valid)
: valid_ (valid),
+ data_member_ (valid),
object_no_id_members_ (valid),
composite_id_members_ (valid),
view_members_ (valid)
{
+ *this >> data_member_names_ >> data_member_;
+
// Find the has_lt_operator function template..
//
has_lt_operator_ = 0;
@@ -1156,6 +1194,8 @@ namespace
object_no_id_members_.traverse (c);
}
}
+
+ names (c);
}
virtual void
@@ -1164,16 +1204,22 @@ namespace
// Make sure we don't have any containers or object pointers.
//
view_members_.traverse (c);
+
+ names (c);
}
virtual void
- traverse_composite (type&)
+ traverse_composite (type& c)
{
+ names (c);
}
bool& valid_;
tree has_lt_operator_;
+ data_member2 data_member_;
+ traversal::names data_member_names_;
+
object_no_id_members object_no_id_members_;
composite_id_members composite_id_members_;
view_members view_members_;