From f8b3ee6d42f5112c4e66a07cc7fdba43ce66aacd Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 27 Apr 2012 13:32:45 +0200 Subject: Support for NULL value semantics for composite values --- odb/relational/source.hxx | 61 ++++++++++++++++++++++++++++++++++------------- odb/validator.cxx | 54 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 95 insertions(+), 20 deletions(-) (limited to 'odb') 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 ("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 ("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_; -- cgit v1.1