aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/common.hxx9
-rw-r--r--odb/context.cxx83
-rw-r--r--odb/context.hxx60
-rw-r--r--odb/pragma.cxx21
-rw-r--r--odb/processor.cxx75
-rw-r--r--odb/relational/pgsql/source.cxx4
-rw-r--r--odb/relational/processor.cxx4
-rw-r--r--odb/relational/source.cxx54
-rw-r--r--odb/relational/source.hxx91
-rw-r--r--odb/validator.cxx17
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<data_member> (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<data_member> (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<regexsub> 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<unsigned long long> ("deleted", 0);
+ unsigned long long v (c.get<unsigned long long> ("deleted", 0));
+
+ if (v != 0 && l != 0)
+ *l = c.get<location_t> ("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<unsigned long long> ("deleted", 0);
+ unsigned long long v (m.get<unsigned long long> ("deleted", 0));
+
+ if (v != 0 && l != 0)
+ *l = m.get<location_t> ("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<unsigned long long> ("deleted", 0));
if (v != 0 && (r == 0 || v < r))
+ {
r = v;
+
+ if (l != 0)
+ *l = (*i)->get<location_t> ("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<semantics::data_member*> ("inverse", 0)
+ return object_pointer (utype (m)) && m.count ("inverse")
+ ? &m.get<data_member_path> ("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<semantics::data_member*> (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<data_member_path> (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<string> ("inverse"));
- location_t loc (m.get<location_t> ("inverse-location"));
+ location_t l (m.get<location_t> ("inverse-location"));
+ data_member_path mp (resolve_data_members (*c, name, l, lex_));
- try
{
- data_member& im (
- c->lookup<data_member> (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<class_&> (e.member_path.front ()->scope ());
@@ -5077,17 +5076,17 @@ traverse_view (type& c)
}
else
{
- c = &static_cast<class_&> (im->scope ());
+ c = &static_cast<class_&> (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 = &lt;
}
@@ -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 = &lt;
}
@@ -5285,26 +5287,22 @@ traverse_view (type& c)
}
else
{
- column_prefix col_prefix;
-
- if (im == 0)
- col_prefix = column_prefix (e.member_path);
-
- instance<object_columns_list> l_cols (col_prefix);
+ instance<object_columns_list> l_cols;
instance<object_columns_list> 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<semantics::class_&> (im->scope ()) : c);
+ poly ? dynamic_cast<semantics::class_&> (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<object_columns> 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*> ("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<iterator, iterator> r (
- rel_map_.equal_range (data_member_path (im)));
-
- using semantics::class_;
+ std::pair<iterator, iterator> 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<class_&> (im.scope ());
+ c = &static_cast<class_&> (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<class_&> (im.scope ());
+ o = &static_cast<class_&> (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<semantics::class_&> (im->scope ()) : c);
+ poly ? dynamic_cast<semantics::class_&> (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<object_columns_list> 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<object_columns_list> 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<object_columns_list> 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<iterator, iterator> 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<semantics::class_&> (im->scope ());
+ c = &dynamic_cast<semantics::class_&> (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<location_t> ("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<location_t> ("deleted-location"));
-
error (dl) << dname << " is deleted after " << pname << endl;
info (pl) << pname << " deletion version is specified here" << endl;