From 521216e0a696fa698c88fc1e18958c82626873cc Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 16 Jun 2015 08:19:25 +0200 Subject: Implement support for nested members in inverse pragma --- odb/common.hxx | 9 ++++ odb/context.cxx | 83 +++++++++++++++++++++++++++++++++++++ odb/context.hxx | 60 +++++++++++++++++++++------ odb/pragma.cxx | 21 +++++++++- odb/processor.cxx | 75 +++++++++++++++------------------ odb/relational/pgsql/source.cxx | 4 +- odb/relational/processor.cxx | 4 +- odb/relational/source.cxx | 54 ++++++++++++------------ odb/relational/source.hxx | 91 +++++++++++++++++++++-------------------- odb/validator.cxx | 17 ++++---- 10 files changed, 276 insertions(+), 142 deletions(-) diff --git a/odb/common.hxx b/odb/common.hxx index 277c0e3..ba9dd2d 100644 --- a/odb/common.hxx +++ b/odb/common.hxx @@ -284,6 +284,15 @@ public: } virtual void + traverse (semantics::data_member& m, column_prefix const& cp) + { + column_prefix op (column_prefix_); + column_prefix_ = cp; + traverse (m); + column_prefix_ = op; + } + + virtual void traverse (semantics::data_member&, semantics::type&, string const& key_prefix, diff --git a/odb/context.cxx b/odb/context.cxx index d62fa88..e6e50b8 100644 --- a/odb/context.cxx +++ b/odb/context.cxx @@ -1317,6 +1317,89 @@ type_val_type (semantics::type& t, return r; } +data_member_path context:: +resolve_data_members (semantics::class_& c, + const string& name, + const location& l, + cxx_string_lexer& lex) +{ + using semantics::class_; + using semantics::data_member; + + data_member_path r; + + // The name was already verified to be syntactically correct so + // we don't need to do any extra error checking in this area. + // + lex.start (name); + + try + { + string tl; + cpp_ttype tt (lex.next (tl)); + + data_member& m (c.lookup (tl, class_::include_hidden)); + + r.push_back (&m); + + if (container (m)) + return r; + + // Resolve nested members if any. + // + for (tt = lex.next (tl); tt == CPP_DOT; tt = lex.next (tl)) + { + lex.next (tl); // Get CPP_NAME. + + data_member& om (*r.back ()); + + // Check that the outer member is composite and also unwrap it while + // at it. + // + class_* comp (composite_wrapper (utype (om))); + if (comp == 0) + { + error (l) << "data member '" << om.name () << "' is not composite" + << endl; + throw operation_failed (); + } + + data_member& nm ( + comp->lookup (tl, class_::include_hidden)); + + r.push_back (&nm); + + if (container (nm)) + return r; + } + } + catch (semantics::unresolved const& e) + { + if (e.type_mismatch) + error (l) << "name '" << e.name << "' does not refer to a data member" + << endl; + else + error (l) << "unable to resolve data member '" << e.name << endl; + + throw operation_failed (); + } + catch (semantics::ambiguous const& e) + { + error (l) << "data member name '" << e.first.name () << "' is ambiguous" + << endl; + + info (e.first.named ().location ()) << "could resolve to " << + "this data member" << endl; + + info (e.second.named ().location ()) << "or could resolve " << + "to this data member" << endl; + + throw operation_failed (); + } + + return r; +} + bool context:: composite_ (semantics::class_& c) { diff --git a/odb/context.hxx b/odb/context.hxx index b32f392..a3a58bf 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -41,6 +41,10 @@ typedef cutl::re::format regex_format; typedef std::vector regex_mapping; +// Forward-declarations. +// +class cxx_string_lexer; + // Generic exception thrown to indicate a failure when diagnostics // has already been issued (to stderr). // @@ -650,6 +654,18 @@ public: bool make_const, string const& var = ""); +public: + // Resolve data member name in the form "a.b.c" to the data member path, + // issuing diagnostics and throwing operation_filed in case of an error. + // This function stops if it encounters a container leaving lex usable + // to continue parsing. + // + data_member_path + resolve_data_members (semantics::class_& scope, + const std::string& name, + const location&, + cxx_string_lexer&); + // Predicates. // public: @@ -799,19 +815,29 @@ public: // Return the deletion version or 0 if not soft-deleted. // static unsigned long long - deleted (semantics::class_& c) + deleted (semantics::class_& c, location_t* l = 0) { - return c.get ("deleted", 0); + unsigned long long v (c.get ("deleted", 0)); + + if (v != 0 && l != 0) + *l = c.get ("deleted-location"); + + return v; } static unsigned long long - deleted (semantics::data_member& m) + deleted (semantics::data_member& m, location_t* l = 0) { - return m.get ("deleted", 0); + unsigned long long v (m.get ("deleted", 0)); + + if (v != 0 && l != 0) + *l = m.get ("deleted-location"); + + return v; } static unsigned long long - deleted (data_member_path const& mp) + deleted (data_member_path const& mp, location_t* l = 0) { unsigned long long r (0); @@ -822,7 +848,12 @@ public: { unsigned long long v ((*i)->get ("deleted", 0)); if (v != 0 && (r == 0 || v < r)) + { r = v; + + if (l != 0) + *l = (*i)->get ("deleted-location"); + } } return r; @@ -1181,6 +1212,9 @@ public: // column_prefix (data_member_path const&, bool last = false); + bool + empty () const {return prefix.empty ();} + void append (semantics::data_member&, string const& key_prefix = string (), @@ -1363,23 +1397,25 @@ public: return pointer_kind (p) == pk_weak; } - static semantics::data_member* + static data_member_path* inverse (semantics::data_member& m) { - return object_pointer (utype (m)) - ? m.get ("inverse", 0) + return object_pointer (utype (m)) && m.count ("inverse") + ? &m.get ("inverse") : 0; } - semantics::data_member* + data_member_path* inverse (semantics::data_member& m, string const& key_prefix) { if (key_prefix.empty ()) return inverse (m); - return object_pointer (member_utype (m, key_prefix)) - ? m.get (key_prefix + "-inverse", 0) - : 0; + if (!object_pointer (member_utype (m, key_prefix))) + return 0; + + string k (key_prefix + "-inverse"); + return m.count (k) ? &m.get (k) : 0; } // Container information. diff --git a/odb/pragma.cxx b/odb/pragma.cxx index ac220b3..b92930a 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -2298,14 +2298,31 @@ handle_pragma (cxx_lexer& l, return; } - val = tl; + string name (tl); - if (l.next (tl, &tn) != CPP_CLOSE_PAREN) + tt = l.next (tl, &tn); + + // Parse nested members if any. + // + for (; tt == CPP_DOT; tt = l.next (tl, &tn)) + { + if (l.next (tl, &tn) != CPP_NAME) + { + error (l) << "name expected after '.' in db pragma " << p << endl; + return; + } + + name += '.'; + name += tl; + } + + if (tt != CPP_CLOSE_PAREN) { error (l) << "')' expected at the end of db pragma " << p << endl; return; } + val = name; tt = l.next (tl, &tn); } else if (p == "on_delete") diff --git a/odb/processor.cxx b/odb/processor.cxx index 3446700..f059d0b 100644 --- a/odb/processor.cxx +++ b/odb/processor.cxx @@ -1272,68 +1272,59 @@ namespace } // See if this is the inverse side of a bidirectional relationship. - // If so, then resolve the member and cache it in the context. + // If so, then resolve the member path and cache it in the context. // if (m.count ("inverse")) { string name (m.get ("inverse")); - location_t loc (m.get ("inverse-location")); + location_t l (m.get ("inverse-location")); + data_member_path mp (resolve_data_members (*c, name, l, lex_)); - try { - data_member& im ( - c->lookup (name, class_::include_hidden)); + string tl; + data_member& m (*mp.back ()); + + if (container (m) && lex_.next (tl) != CPP_EOF) + { + error (l) << "unexpect name after container member " << + m.name () << " in '#pragma db inverse'" << endl; + throw operation_failed (); + } + } + + // Validate each member. + // + for (data_member_path::iterator i (mp.begin ()); i != mp.end (); ++i) + { + data_member& im (**i); + const string& n (im.name ()); if (im.count ("transient")) { - error (loc) << "data member '" << name << "' specified with " << + error (l) << "data member '" << n << "' specified with " << "'#pragma db inverse' is transient" << endl; - info (im.location ()) << "data member '" << name << "' is " << + info (im.location ()) << "data member '" << n << "' is " << "defined here" << endl; throw operation_failed (); } if (im.count ("inverse") || im.count ("value-inverse")) { - error (loc) << "data member '" << name << "' specified with " << - "'#pragma db inverse' is inverse" << endl; - info (im.location ()) << "data member '" << name << "' is " << + error (l) << "data member '" << n << "' specified with " << + "'#pragma db inverse' is itself inverse" << endl; + info (im.location ()) << "data member '" << n << "' is " << "defined here" << endl; throw operation_failed (); } - - // @@ Would be good to check that the other end is actually - // an object pointer/points_to and points to the correct - // object. But the other class may not have been processed - // yet. Need to do in validator, pass 2. - // - m.remove ("inverse"); - m.set (kp + (kp.empty () ? "": "-") + "inverse", &im); - } - catch (semantics::unresolved const& e) - { - if (e.type_mismatch) - error (loc) << "name '" << name << "' in '#pragma db " << - "inverse' does not refer to a data member" << endl; - else - error (loc) << "unable to resolve data member '" << name << - "' specified with '#pragma db inverse'" << endl; - - throw operation_failed (); } - catch (semantics::ambiguous const& e) - { - error (loc) << "data member name '" << name << "' specified " << - "with '#pragma db inverse' is ambiguous" << endl; - - info (e.first.named ().location ()) << "could resolve to this " << - "data member" << endl; - info (e.second.named ().location ()) << "or could resolve to " << - "this data member" << endl; - - throw operation_failed (); - } + // @@ Would be good to check that the other end is actually + // an object pointer/points_to and points to the correct + // object. But the other class may not have been processed + // yet. Need to do in validator, pass 2. + // + m.remove ("inverse"); + m.set (kp + (kp.empty () ? "": "-") + "inverse", mp); } return c; @@ -1904,6 +1895,8 @@ namespace tree wrapper_traits_; tree pointer_traits_; tree container_traits_; + + cxx_string_lexer lex_; }; struct view_data_member: traversal::data_member, context diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index ec900dc..d009a7c 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -873,8 +873,8 @@ namespace relational string const& pn (public_name (m)); string scope (scope_ + "::" + flat_prefix_ + pn + "_traits"); - semantics::data_member* inv_m (inverse (m, "value")); - bool inv (inv_m != 0); + data_member_path* imp (inverse (m, "value")); + bool inv (imp != 0); bool smart (!inv && !unordered (m) && container_smart (t)); diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index 782abcf..0dbacbd 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -1536,9 +1536,9 @@ namespace relational // miss it since we don't examine inside poly bases on the // backwards scan (see above). // - if (semantics::data_member* im = inverse (m)) + if (data_member_path* imp = inverse (m)) { - if (&im->scope () == &c) // Direct member. + if (&imp->front ()->scope () == &c) // Direct member. return; } diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index 4540bb4..c2144b4 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -4912,7 +4912,7 @@ traverse_view (type& c) using semantics::data_member; data_member& m (*e.member_path.back ()); - data_member* im (inverse (m)); + data_member_path* imp (inverse (m)); // Resolve the pointed-to object to view_object and do // some sanity checks while at it. @@ -4989,11 +4989,10 @@ traverse_view (type& c) // e.vo - us // e.member_path - in us // - if (im == 0) + if (imp == 0) rel_map.insert (make_pair (e.member_path, make_pair (e.vo, vo))); else - rel_map.insert ( - make_pair (data_member_path (*im), make_pair (vo, e.vo))); + rel_map.insert (make_pair (*imp, make_pair (vo, e.vo))); // Left and right-hand side table names. // @@ -5042,7 +5041,7 @@ traverse_view (type& c) // First join the container table if necessary. // - semantics::type* cont (container (im != 0 ? *im : m)); + semantics::type* cont (container (imp != 0 ? *imp->back () : m)); string ct; // Container table. if (cont != 0) @@ -5063,10 +5062,10 @@ traverse_view (type& c) // In a polymorphic hierarchy the member can be in a base (see // above). // - if (class_* root = polymorphic (im != 0 ? *vo->obj : *e.vo->obj)) + if (class_* root = polymorphic (imp != 0 ? *vo->obj : *e.vo->obj)) { class_* c; - if (im == 0) + if (imp == 0) { c = &static_cast (e.member_path.front ()->scope ()); @@ -5077,17 +5076,17 @@ traverse_view (type& c) } else { - c = &static_cast (im->scope ()); + c = &static_cast (imp->front ()->scope ()); if (!polymorphic (*c)) c = root; - t = table_name (*im, table_prefix (*c)); + t = table_name (*c, *imp); } } else - t = im != 0 - ? table_name (*im, table_prefix (*vo->obj)) + t = imp != 0 + ? table_name (*vo->obj, *imp) : table_name (*e.vo->obj, e.member_path); // The tricky part is to figure out which view_object, vo @@ -5096,7 +5095,7 @@ traverse_view (type& c) // might not make intuitive sense, but it has been verified // with the truth table. // - string const& a (im != 0 ? vo->alias : e.vo->alias); + string const& a (imp != 0 ? vo->alias : e.vo->alias); if (a.empty ()) { @@ -5124,15 +5123,17 @@ traverse_view (type& c) qname* ot; // Object table (either lt or rt). - if (im != 0) + if (imp != 0) { + semantics::data_member& imb (*imp->back ()); + if (&o == c) { // container.value = pointer.id // semantics::data_member& id (*id_member (*e.vo->obj)); - c_cols->traverse (*im, utype (id), "value", "value"); + c_cols->traverse (imb, utype (id), "value", "value"); o_cols->traverse (id); ot = < } @@ -5142,8 +5143,7 @@ traverse_view (type& c) // semantics::data_member& id (*id_member (*vo->obj)); - c_cols->traverse ( - *im, utype (id), "id", "object_id", vo->obj); + c_cols->traverse (imb, utype (id), "id", "object_id", vo->obj); o_cols->traverse (id); ot = &rt; } @@ -5217,15 +5217,17 @@ traverse_view (type& c) qname* ot; // Object table (either lt or rt). - if (im != 0) + if (imp != 0) { + semantics::data_member& imb (*imp->back ()); + if (&o == c) { // container.id = pointed-to.id // semantics::data_member& id (*id_member (*vo->obj)); - c_cols->traverse (*im, utype (id), "id", "object_id", vo->obj); + c_cols->traverse (imb, utype (id), "id", "object_id", vo->obj); o_cols->traverse (id); ot = &rt; } @@ -5235,7 +5237,7 @@ traverse_view (type& c) // semantics::data_member& id (*id_member (*e.vo->obj)); - c_cols->traverse (*im, utype (id), "value", "value"); + c_cols->traverse (imb, utype (id), "value", "value"); o_cols->traverse (id); ot = < } @@ -5285,26 +5287,22 @@ traverse_view (type& c) } else { - column_prefix col_prefix; - - if (im == 0) - col_prefix = column_prefix (e.member_path); - - instance l_cols (col_prefix); + instance l_cols; instance r_cols; - if (im != 0) + if (imp != 0) { // our.id = pointed-to.pointer // l_cols->traverse (*id_member (*e.vo->obj)); - r_cols->traverse (*im); + r_cols->traverse (*imp->back (), column_prefix (*imp)); } else { // our.pointer = pointed-to.id // - l_cols->traverse (*e.member_path.back ()); + l_cols->traverse (*e.member_path.back (), + column_prefix (e.member_path)); r_cols->traverse (*id_member (*vo->obj)); } diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 716aa10..7774739 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -188,31 +188,33 @@ namespace relational if (sk_ == statement_select && m.count ("polymorphic-ref")) return; - semantics::data_member* im (inverse (m, key_prefix_)); + data_member_path* imp (inverse (m, key_prefix_)); // Ignore certain columns depending on what kind of statement we are // generating. Columns corresponding to the inverse members are // only present in the select statements. // - if (im != 0 && sk_ != statement_select) + if (imp != 0 && sk_ != statement_select) return; // Inverse object pointers come from a joined table. // - if (im != 0) + if (imp != 0) { bool poly (polymorphic (c) != 0); + semantics::data_member& imf (*imp->front ()); + semantics::data_member& imb (*imp->back ()); // In a polymorphic hierarchy the inverse member can be in // the base class, in which case we should use that table. // semantics::class_& imc ( - poly ? dynamic_cast (im->scope ()) : c); + poly ? dynamic_cast (imf.scope ()) : c); semantics::data_member& id (*id_member (imc)); semantics::type& idt (utype (id)); - if (container (*im)) + if (container (imb)) { // This container is a direct member of the class so the table // prefix is just the class table name. We don't assign join @@ -229,11 +231,11 @@ namespace relational if (table_name_resolver_ != 0) table = table_name_resolver_->resolve_pointer (m); else - table = table_qname (*im, table_prefix (imc)); + table = table_qname (imc, *imp); } instance oc (table, sk_, sc_); - oc->traverse (*im, idt, "id", "object_id", &imc); + oc->traverse (imb, idt, "id", "object_id", &imc); } else { @@ -373,14 +375,14 @@ namespace relational { view_object& us (*ptr_->get ("view-object")); - semantics::data_member& im (*inverse (m)); + data_member_path& imp (*inverse (m)); + semantics::data_member& imf (*imp.front ()); + semantics::data_member& imb (*imp.back ()); + using semantics::class_; typedef view_relationship_map::const_iterator iterator; - std::pair r ( - rel_map_.equal_range (data_member_path (im))); - - using semantics::class_; + std::pair r (rel_map_.equal_range (imp)); for (; r.first != r.second; ++r.first) { @@ -396,7 +398,7 @@ namespace relational { // Can be in base. // - c = &static_cast (im.scope ()); + c = &static_cast (imf.scope ()); if (!polymorphic (*c)) c = root; @@ -404,13 +406,13 @@ namespace relational string const& a (vo.alias); - if (container (im)) + if (container (imb)) { // If this is a container, then object_columns will use the // column from the container table, not from the object table // (which, strictly speaking, might not have been JOIN'ed). // - qname t (table_name (im, table_prefix (*c))); + qname t (table_name (*c, imp)); return a.empty () ? quote_id (t) : quote_id (a + '_' + t.uname ()); @@ -447,7 +449,7 @@ namespace relational class_* o (object_pointer (utype (m))); if (class_* root = polymorphic (*o)) { - o = &static_cast (im.scope ()); + o = &static_cast (imf.scope ()); if (!polymorphic (*o)) o = root; @@ -456,11 +458,7 @@ namespace relational string const& a (us.alias); string lt (a.empty () ? table_qname (*us.obj) : quote_id (a)); string rt; - - qname ct ( - container (im) - ? table_name (im, table_prefix (*o)) - : table_name (*o)); + qname ct (container (imb) ? table_name (*o, imp) : table_name (*o)); string l ("LEFT JOIN "); @@ -490,10 +488,10 @@ namespace relational l_cols->traverse (id); - if (container (im)) - r_cols->traverse (im, utype (id), "value", "value"); + if (container (imb)) + r_cols->traverse (imb, utype (id), "value", "value"); else - r_cols->traverse (im); + r_cols->traverse (imb, column_prefix (imp)); for (object_columns_list::iterator b (l_cols->begin ()), i (b), j (r_cols->begin ()); i != l_cols->end (); ++i, ++j) @@ -973,25 +971,28 @@ namespace relational semantics::class_* joined_obj (0); - if (semantics::data_member* im = inverse (m, key_prefix_)) + if (data_member_path* imp = inverse (m, key_prefix_)) { + semantics::data_member& imf (*imp->front ()); + semantics::data_member& imb (*imp->back ()); + // In a polymorphic hierarchy the inverse member can be in // the base class, in which case we should use that table. // semantics::class_& imc ( - poly ? dynamic_cast (im->scope ()) : c); + poly ? dynamic_cast (imf.scope ()) : c); - if (container (*im)) + if (container (imb)) { // This container is a direct member of the class so the table // prefix is just the class table name. // - t = table_qname (*im, table_prefix (imc)); + t = table_qname (imc, *imp); // Container's value is our id. // instance id_cols; - id_cols->traverse (*im, utype (id_), "value", "value"); + id_cols->traverse (imb, utype (id_), "value", "value"); for (object_columns_list::iterator b (id_cols->begin ()), i (b), j (id_cols_->begin ()); i != id_cols->end (); ++i, ++j) @@ -1021,7 +1022,7 @@ namespace relational instance oid_cols, cid_cols; oid_cols->traverse (id); - cid_cols->traverse (*im, utype (id), "id", "object_id", &c); + cid_cols->traverse (imb, utype (id), "id", "object_id", &c); for (object_columns_list::iterator b (cid_cols->begin ()), i (b), j (oid_cols->begin ()); i != cid_cols->end (); ++i, ++j) @@ -1045,7 +1046,7 @@ namespace relational a = quote_id (poly ? alias + "_" + table.uname () : alias); instance id_cols; - id_cols->traverse (*im); + id_cols->traverse (imb, column_prefix (*imp)); for (object_columns_list::iterator b (id_cols->begin ()), i (b), j (id_cols_->begin ()); i != id_cols->end (); ++i, ++j) @@ -1210,7 +1211,6 @@ namespace relational traverse_container (semantics::data_member& m, semantics::type& t) { semantics::type& vt (container_vt (t)); - semantics::data_member* im (inverse (m, "value")); if (semantics::class_* cvt = composite_wrapper (vt)) { @@ -1222,12 +1222,12 @@ namespace relational session_ = session_ || t->session_; } else if (semantics::class_* c = object_pointer (vt)) - check (m, im, vt, *c); + check (m, inverse (m, "value"), vt, *c); } void check (semantics::data_member& m, - semantics::data_member* im, + data_member_path* imp, semantics::type& pt, // Pointer type. semantics::class_& c) { @@ -1257,13 +1257,12 @@ namespace relational typedef view_relationship_map::const_iterator iterator; std::pair r ( - rel_map_.equal_range ( - im != 0 ? data_member_path (*im) : member_path_)); + rel_map_.equal_range (imp != 0 ? *imp : member_path_)); if (r.first == r.second) return; // This relationship does not figure in the view. - view_object& vo (*(im != 0 + view_object& vo (*(imp != 0 ? r.first->second.first : r.first->second.second)); @@ -3393,10 +3392,10 @@ namespace relational type* it (0); type* kt (0); - semantics::data_member* im (context::inverse (m, "value")); + data_member_path* imp (context::inverse (m, "value")); bool ordered (false); - bool inverse (im != 0); + bool inverse (imp != 0); bool grow (false); switch (ck) @@ -3504,13 +3503,15 @@ namespace relational if (inverse) { semantics::class_* c (object_pointer (vt)); + semantics::data_member& imf (*imp->front ()); + semantics::data_member& imb (*imp->back ()); // In a polymorphic hierarchy the inverse member can be in // the base class, in which case we should use that class // for the table name, etc. // if (polymorphic (*c)) - c = &dynamic_cast (im->scope ()); + c = &dynamic_cast (imf.scope ()); semantics::data_member& inv_id (*id_member (*c)); @@ -3521,7 +3522,7 @@ namespace relational // column (ref to us). statement_columns sc; - if (container (*im)) + if (container (imb)) { // many(i)-to-many // @@ -3529,11 +3530,11 @@ namespace relational // This other container is a direct member of the class so the // table prefix is just the class table name. // - inv_table = table_name (*im, table_prefix (*c)); + inv_table = table_name (*c, *imp); inv_qtable = quote_id (inv_table); - inv_id_cols->traverse (*im, utype (inv_id), "id", "object_id", c); - inv_fid_cols->traverse (*im, idt, "value", "value"); + inv_id_cols->traverse (imb, utype (inv_id), "id", "object_id", c); + inv_fid_cols->traverse (imb, idt, "value", "value"); for (object_columns_list::iterator i (inv_id_cols->begin ()); i != inv_id_cols->end (); ++i) @@ -3558,7 +3559,7 @@ namespace relational inv_qtable = quote_id (inv_table); inv_id_cols->traverse (inv_id); - inv_fid_cols->traverse (*im); + inv_fid_cols->traverse (imb, column_prefix (*imp)); for (object_columns_list::iterator i (inv_id_cols->begin ()); i != inv_id_cols->end (); ++i) diff --git a/odb/validator.cxx b/odb/validator.cxx index 071da16..561d348 100644 --- a/odb/validator.cxx +++ b/odb/validator.cxx @@ -1192,8 +1192,8 @@ namespace // Inverse pointer must be deleted before the direct side. // - if (semantics::data_member* im = inverse (m)) - check_strict (m, *im, "inverse object pointer", "direct pointer"); + if (data_member_path* imp = inverse (m)) + check_strict (m, *imp, "inverse object pointer", "direct pointer"); } virtual void @@ -1209,8 +1209,8 @@ namespace // Inverse pointer must be deleted before the direct side. // - if (semantics::data_member* im = inverse (m, "value")) - check_strict (m, *im, "inverse object pointer", "direct pointer"); + if (data_member_path* imp = inverse (m, "value")) + check_strict (m, *imp, "inverse object pointer", "direct pointer"); } } @@ -1246,14 +1246,13 @@ namespace void check_strict (D& dep, P& pre, char const* dname, char const* pname) { - unsigned long long dv (deleted (dep)); - unsigned long long pv (deleted (pre)); + location_t dl, pl; + unsigned long long dv (deleted (dep, &dl)); + unsigned long long pv (deleted (pre, &pl)); if (pv == 0) // Prerequisite never deleted. return; - location_t pl (pre.template get ("deleted-location")); - if (dv == 0) // Dependent never deleted. { location dl (dep.location ()); @@ -1265,8 +1264,6 @@ namespace } else if (pv > dv) // Prerequisite deleted before dependent. { - location_t dl (dep.template get ("deleted-location")); - error (dl) << dname << " is deleted after " << pname << endl; info (pl) << pname << " deletion version is specified here" << endl; -- cgit v1.1