aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/context.hxx16
-rw-r--r--odb/pragma.cxx91
-rw-r--r--odb/pragma.hxx6
-rw-r--r--odb/relational/header.hxx26
-rw-r--r--odb/relational/inline.hxx4
-rw-r--r--odb/relational/processor.cxx52
-rw-r--r--odb/relational/source.cxx4
-rw-r--r--odb/relational/source.hxx136
8 files changed, 261 insertions, 74 deletions
diff --git a/odb/context.hxx b/odb/context.hxx
index 550b64e..f91568a 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -113,7 +113,7 @@ struct default_value
tree node;
};
-//
+// Object or table associated with the view.
//
struct view_object
{
@@ -122,21 +122,29 @@ struct view_object
std::string
name () const
{
- return alias.empty () ? object->name () : alias;
+ if (!alias.empty ())
+ return alias;
+
+ return kind == object ? obj->name () : orig_name;
}
- tree node;
+ enum kind_type { object, table };
+
+ kind_type kind;
+ tree node; // Tree node if kind is object.
std::string orig_name; // Original name as specified in the pragma.
std::string alias;
tree scope;
location_t loc;
- semantics::class_* object;
+ semantics::class_* obj;
cxx_tokens cond; // Join condition tokens.
};
typedef std::vector<view_object> view_objects;
+// The view_alias_map does not contain entries for tables.
+//
typedef std::map<std::string, view_object*> view_alias_map;
typedef std::map<tree, view_object*> view_object_map;
diff --git a/odb/pragma.cxx b/odb/pragma.cxx
index 2fb6d27..56cf7c9 100644
--- a/odb/pragma.cxx
+++ b/odb/pragma.cxx
@@ -443,6 +443,22 @@ check_spec_decl_type (tree d,
}
static void
+add_pragma (pragma const& prag, tree decl)
+{
+ if (decl)
+ decl_pragmas_[decl].insert (prag);
+ else
+ {
+ tree scope (current_scope ());
+
+ if (!CLASS_TYPE_P (scope))
+ scope = global_namespace;
+
+ loc_pragmas_[scope].push_back (prag);
+ }
+}
+
+static void
handle_pragma (cpp_reader* reader,
string const& p,
tree decl,
@@ -459,6 +475,7 @@ handle_pragma (cpp_reader* reader,
if (p == "table")
{
// table ("<name>")
+ // table ("<name>" [= "<alias>"] [: "<cond>"] (view only)
//
// Make sure we've got the correct declaration type.
@@ -480,14 +497,69 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = string (TREE_STRING_POINTER (t));
+ // The table specifier is used for both objects and views. In case
+ // of an object, the context values is just a string. In case of a
+ // view, the context value is a view_object entry. The problem is
+ // that at this stage we don't know whether we are dealing with an
+ // object or a view. To resolve this in a somewhat hackish way, we
+ // are going to create both a string and a view_object entry.
+ //
+ view_object vo;
+ vo.kind = view_object::table;
+ vo.orig_name = TREE_STRING_POINTER (t);
- if (pragma_lex (&t) != CPP_CLOSE_PAREN)
+ tt = pragma_lex (&t);
+
+ if (tt == CPP_EQ)
+ {
+ // We have an alias.
+ //
+ if (pragma_lex (&t) != CPP_STRING)
+ {
+ error ()
+ << "table alias expected after '=' in db pragma " << p << endl;
+ return;
+ }
+
+ vo.alias = TREE_STRING_POINTER (t);
+ tt = pragma_lex (&t);
+ }
+
+ if (tt == CPP_COLON)
+ {
+ // We have a condition.
+
+ tt = pragma_lex (&t);
+
+ if (!parse_expression (t, tt, vo.cond, p))
+ return; // Diagnostics has already been issued.
+
+ if (vo.cond.empty ())
+ {
+ error ()
+ << "join condition expected after ':' in db pragma " << p << endl;
+ return;
+ }
+ }
+
+ if (tt != CPP_CLOSE_PAREN)
{
error () << "')' expected at the end of db pragma " << p << endl;
return;
}
+ // Add the "table" pragma.
+ //
+ if (vo.alias.empty () && vo.cond.empty ())
+ add_pragma (
+ pragma (p, name, vo.orig_name, loc, &check_spec_decl_type, 0), decl);
+
+ vo.scope = current_scope ();
+ vo.loc = loc;
+ val = vo;
+ name = "objects";
+ adder = &accumulate<view_object>;
+
tt = pragma_lex (&t);
}
else if (p == "pointer")
@@ -723,6 +795,7 @@ handle_pragma (cpp_reader* reader,
}
view_object vo;
+ vo.kind = view_object::object;
vo.node = resolve_scoped_name (t, tt, vo.orig_name, true, p);
if (vo.node == 0)
@@ -1360,19 +1433,7 @@ handle_pragma (cpp_reader* reader,
// Record this pragma.
//
- pragma prag (p, name, val, loc, &check_spec_decl_type, adder);
-
- if (decl)
- decl_pragmas_[decl].insert (prag);
- else
- {
- tree scope (current_scope ());
-
- if (!CLASS_TYPE_P (scope))
- scope = global_namespace;
-
- loc_pragmas_[scope].push_back (prag);
- }
+ add_pragma (pragma (p, name, val, loc, &check_spec_decl_type, adder), decl);
// See if there are any more pragmas.
//
diff --git a/odb/pragma.hxx b/odb/pragma.hxx
index ba4aab8..0b09b43 100644
--- a/odb/pragma.hxx
+++ b/odb/pragma.hxx
@@ -52,10 +52,10 @@ struct pragma
operator< (pragma const& y) const
{
if (add == 0)
- return pragma_name < y.pragma_name;
+ return context_name < y.context_name;
else
- return pragma_name < y.pragma_name ||
- (pragma_name == y.pragma_name && loc < y.loc);
+ return context_name < y.context_name ||
+ (context_name == y.context_name && loc < y.loc);
}
std::string pragma_name; // Actual pragma name for diagnostics.
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 50a40b2..1380c49 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -1258,11 +1258,13 @@ namespace relational
// query_type
//
- if (c.count ("objects"))
+ size_t obj_count (c.get<size_t> ("object-count"));
+
+ if (obj_count != 0)
{
view_objects& objs (c.get<view_objects> ("objects"));
- if (objs.size () > 1)
+ if (obj_count > 1)
{
os << "struct query_columns"
<< "{";
@@ -1271,8 +1273,11 @@ namespace relational
i < objs.end ();
++i)
{
+ if (i->kind != view_object::object)
+ continue; // Skip tables.
+
bool alias (!i->alias.empty ());
- semantics::class_& o (*i->object);
+ semantics::class_& o (*i->obj);
string const& name (alias ? i->alias : o.name ());
string const& type (o.fq_name ());
@@ -1306,13 +1311,20 @@ namespace relational
// For a single object view we generate a shortcut without
// an intermediate typedef.
//
- view_object const& vo (objs[0]);
+ view_object const* vo (0);
+ for (view_objects::const_iterator i (objs.begin ());
+ vo == 0 && i < objs.end ();
+ ++i)
+ {
+ if (i->kind == view_object::object)
+ vo = &*i;
+ }
- bool alias (!vo.alias.empty ());
- semantics::class_& o (*vo.object);
+ bool alias (!vo->alias.empty ());
+ semantics::class_& o (*vo->obj);
string const& type (o.fq_name ());
- if (alias && vo.alias != table_name (o))
+ if (alias && vo->alias != table_name (o))
os << "static const char query_alias[];"
<< endl
<< "struct query_type:" << endl
diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx
index 9abc86f..78d81bf 100644
--- a/odb/relational/inline.hxx
+++ b/odb/relational/inline.hxx
@@ -274,7 +274,9 @@ namespace relational
// query_type
//
- if (c.count ("objects"))
+ size_t obj_count (c.get<size_t> ("object-count"));
+
+ if (obj_count != 0)
{
os << "inline" << endl
<< traits << "::query_type::" << endl
diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx
index 82852f0..83adb39 100644
--- a/odb/relational/processor.cxx
+++ b/odb/relational/processor.cxx
@@ -1169,7 +1169,7 @@ namespace relational
if (j != amap_.end ())
{
i->table = j->first;
- obj = j->second->object;
+ obj = j->second->obj;
// Skip '::'.
//
@@ -1215,7 +1215,7 @@ namespace relational
throw operation_failed ();
}
- obj = j->second->object;
+ obj = j->second->obj;
i->table = table_name (*obj);
}
@@ -1308,7 +1308,10 @@ namespace relational
member_resolver resolver (exact_members, pub_members, m);
for (view_objects::iterator i (objs.begin ()); i != objs.end (); ++i)
- resolver.traverse (*i);
+ {
+ if (i->kind == view_object::object)
+ resolver.traverse (*i);
+ }
assoc_members& members (
!exact_members.empty () ? exact_members : pub_members);
@@ -1362,7 +1365,7 @@ namespace relational
ep.kind = column_expr_part::reference;
ep.table = am.vo->alias.empty ()
- ? table_name (*am.vo->object)
+ ? table_name (*am.vo->obj)
: am.vo->alias;
ep.member_path.push_back (am.m);
@@ -1395,7 +1398,7 @@ namespace relational
traverse (view_object& vo)
{
member_.vo_ = &vo;
- traverse (*vo.object);
+ traverse (*vo.obj);
}
virtual void
@@ -1636,6 +1639,9 @@ namespace relational
view_alias_map& amap (c.set ("alias-map", view_alias_map ()));
view_object_map& omap (c.set ("object-map", view_object_map ()));
+ size_t& obj_count (c.set ("object-count", size_t (0)));
+ size_t& tbl_count (c.set ("table-count", size_t (0)));
+
if (has_o)
{
using semantics::class_;
@@ -1644,6 +1650,25 @@ namespace relational
for (view_objects::iterator i (objs.begin ()); i != objs.end (); ++i)
{
+ if (i->kind != view_object::object)
+ {
+ // Make sure we have join conditions for tables unless it
+ // is the first entry.
+ //
+ if (i != objs.begin () && i->cond.empty ())
+ {
+ error (i->loc)
+ << "missing join condition in db pragma table" << endl;
+
+ throw operation_failed ();
+ }
+
+ tbl_count++;
+ continue;
+ }
+ else
+ obj_count++;
+
tree n (TYPE_MAIN_VARIANT (i->node));
if (TREE_CODE (n) != RECORD_TYPE)
@@ -1669,7 +1694,7 @@ namespace relational
throw operation_failed ();
}
- i->object = &o;
+ i->obj = &o;
if (i->alias.empty ())
{
@@ -1716,6 +1741,9 @@ namespace relational
//
for (view_objects::iterator j (objs.begin ()); j != i; ++j)
{
+ if (j->kind != view_object::object)
+ continue; // Skip tables.
+
// First see if any of the objects that were specified
// prior to this object point to it.
//
@@ -1785,7 +1813,7 @@ namespace relational
relationship const& r (rs.back ());
string name (r.pointer->alias.empty ()
- ? r.pointer->object->fq_name ()
+ ? r.pointer->obj->fq_name ()
: r.pointer->alias);
name += "::";
name += r.name;
@@ -1832,7 +1860,7 @@ namespace relational
traverse (view_object& pointer)
{
pointer_ = &pointer;
- object_members_base::traverse (*pointer.object);
+ object_members_base::traverse (*pointer.obj);
}
virtual void
@@ -1849,10 +1877,10 @@ namespace relational
// Ignore self-pointers if requested.
//
- if (!self_pointer_ && pointer_->object == c)
+ if (!self_pointer_ && pointer_->obj == c)
return;
- if (pointee_.object == c)
+ if (pointee_.obj == c)
{
relationships_.push_back (relationship ());
relationships_.back ().member = &m;
@@ -1874,10 +1902,10 @@ namespace relational
// Ignore self-pointers if requested.
//
- if (!self_pointer_ && pointer_->object == c)
+ if (!self_pointer_ && pointer_->obj == c)
return;
- if (pointee_.object == c)
+ if (pointee_.obj == c)
{
relationships_.push_back (relationship ());
relationships_.back ().member = &m;
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 6b364cf..5dfc15a 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -138,7 +138,7 @@ namespace relational
tt = lex.next (t);
decl = lookup::resolve_scoped_name (
- t, tt, ptt, lex, vo->object->tree_node (), name, false);
+ t, tt, ptt, lex, vo->obj->tree_node (), name, false);
}
}
@@ -172,7 +172,7 @@ namespace relational
if (multi_obj)
{
r += "::";
- r += vo->object->name ();
+ r += vo->obj->name ();
}
}
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 3474f15..fbe9b1c 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -2959,17 +2959,22 @@ namespace relational
// query_type
//
- if (c.count ("objects"))
+ size_t obj_count (c.get<size_t> ("object-count"));
+
+ if (obj_count != 0)
{
view_objects& objs (c.get<view_objects> ("objects"));
- if (objs.size () > 1)
+ if (obj_count > 1)
{
for (view_objects::const_iterator i (objs.begin ());
i < objs.end ();
++i)
{
- if (!i->alias.empty () && i->alias != table_name (*i->object))
+ if (i->kind != view_object::object)
+ continue; // Skip tables.
+
+ if (!i->alias.empty () && i->alias != table_name (*i->obj))
os << "const char " << traits << "::query_columns::" << endl
<< i->alias << "_alias_[] = " << strlit (i->alias) << ";"
<< endl;
@@ -2980,11 +2985,18 @@ namespace relational
// For a single object view we generate a shortcut without
// an intermediate typedef.
//
- view_object const& vo (objs[0]);
+ view_object const* vo (0);
+ for (view_objects::const_iterator i (objs.begin ());
+ vo == 0 && i < objs.end ();
+ ++i)
+ {
+ if (i->kind == view_object::object)
+ vo = &*i;
+ }
- if (!vo.alias.empty () && vo.alias != table_name (*vo.object))
+ if (!vo->alias.empty () && vo->alias != table_name (*vo->obj))
os << "const char " << traits << "::" << endl
- << "query_alias[] = " << strlit (vo.alias) << ";"
+ << "query_alias[] = " << strlit (vo->alias) << ";"
<< endl;
}
}
@@ -3119,14 +3131,78 @@ namespace relational
i != objs.end ();
++i)
{
+ bool first (i == objs.begin ());
string l;
+ //
+ // Tables.
+ //
+
+ if (i->kind == view_object::table)
+ {
+ if (first)
+ {
+ l = "FROM ";
+ l += quote_id (i->orig_name);
+
+ if (!i->alias.empty ())
+ {
+ l += " AS ";
+ l += quote_id (i->alias);
+ }
+
+ os << "r += " << strlit (l) << ";"
+ << endl;
+
+ continue;
+ }
+
+ l = "LEFT JOIN ";
+ l += quote_id (i->orig_name);
+
+ if (!i->alias.empty ())
+ {
+ l += " AS ";
+ l += quote_id (i->alias);
+ }
+
+ expression e (
+ translate_expression (
+ c, i->cond, i->scope, i->loc, "table"));
+
+ if (e.kind != expression::literal)
+ {
+ error (i->loc)
+ << "invalid join condition in db pragma table" << endl;
+
+ throw operation_failed ();
+ }
+
+ l += " ON";
+
+ os << "r += " << strlit (l) << ";"
+ // Output the pragma location for easier error tracking.
+ //
+ << "// From " <<
+ location_file (i->loc).leaf () << ":" <<
+ location_line (i->loc) << ":" <<
+ location_column (i->loc) << endl
+ << "r += " << e.value << ";"
+ << endl;
+
+ continue;
+ }
+
+ //
+ // Objects.
+ //
+
// First object.
//
- if (i == objs.begin ())
+ if (first)
{
l = "FROM ";
- l += table_qname (*i->object);
+ l += table_qname (*i->obj);
if (!i->alias.empty ())
{
@@ -3149,7 +3225,7 @@ namespace relational
if (e.kind == expression::literal)
{
l = "LEFT JOIN ";
- l += table_qname (*i->object);
+ l += table_qname (*i->obj);
if (!i->alias.empty ())
{
@@ -3198,7 +3274,7 @@ namespace relational
// pointer to ourselves is always assumed to point
// to this association.
//
- if (i->object == c)
+ if (i->obj == c)
vo = &*i;
else
{
@@ -3208,7 +3284,7 @@ namespace relational
j != i;
++j)
{
- if (j->object != c)
+ if (j->obj != c)
continue;
if (vo == 0)
@@ -3262,11 +3338,11 @@ namespace relational
// Left and right-hand side table names.
//
string lt (e.vo->alias.empty ()
- ? table_name (*e.vo->object)
+ ? table_name (*e.vo->obj)
: e.vo->alias);
string rt (vo->alias.empty ()
- ? table_name (*vo->object)
+ ? table_name (*vo->obj)
: vo->alias);
// First join the container table if necessary.
@@ -3288,11 +3364,11 @@ namespace relational
// function would have to return a member path instead
// of just a single member.
//
- table_prefix tp (table_name (*vo->object) + "_", 1);
+ table_prefix tp (table_name (*vo->obj) + "_", 1);
ct = table_qname (*im, tp);
}
else
- ct = table_qname (*e.vo->object, e.member_path);
+ ct = table_qname (*e.vo->obj, e.member_path);
}
if (cont != 0)
@@ -3309,7 +3385,7 @@ namespace relational
//
if (im != 0)
{
- if (i->object == c)
+ if (i->obj == c)
{
// container.value = pointer.id
//
@@ -3319,7 +3395,7 @@ namespace relational
l += "=";
l += quote_id (lt);
l += '.';
- l += column_qname (*id_member (*e.vo->object));
+ l += column_qname (*id_member (*e.vo->obj));
}
else
{
@@ -3331,12 +3407,12 @@ namespace relational
l += "=";
l += quote_id (rt);
l += '.';
- l += column_qname (*id_member (*vo->object));
+ l += column_qname (*id_member (*vo->obj));
}
}
else
{
- if (i->object == c)
+ if (i->obj == c)
{
// container.id = pointer.id
//
@@ -3346,7 +3422,7 @@ namespace relational
l += "=";
l += quote_id (lt);
l += '.';
- l += column_qname (*id_member (*e.vo->object));
+ l += column_qname (*id_member (*e.vo->obj));
}
else
{
@@ -3358,7 +3434,7 @@ namespace relational
l += "=";
l += quote_id (rt);
l += '.';
- l += column_qname (*id_member (*vo->object));
+ l += column_qname (*id_member (*vo->obj));
}
}
@@ -3366,7 +3442,7 @@ namespace relational
}
l = "LEFT JOIN ";
- l += table_qname (*i->object);
+ l += table_qname (*i->obj);
if (!i->alias.empty ())
{
@@ -3381,7 +3457,7 @@ namespace relational
{
if (im != 0)
{
- if (i->object == c)
+ if (i->obj == c)
{
// container.id = pointed-to.id
//
@@ -3391,7 +3467,7 @@ namespace relational
l += "=";
l += quote_id (rt);
l += '.';
- l += column_qname (*id_member (*vo->object));
+ l += column_qname (*id_member (*vo->obj));
}
else
{
@@ -3403,12 +3479,12 @@ namespace relational
l += "=";
l += quote_id (lt);
l += '.';
- l += column_qname (*id_member (*e.vo->object));
+ l += column_qname (*id_member (*e.vo->obj));
}
}
else
{
- if (i->object == c)
+ if (i->obj == c)
{
// container.value = pointed-to.id
//
@@ -3418,7 +3494,7 @@ namespace relational
l += "=";
l += quote_id (rt);
l += '.';
- l += column_qname (*id_member (*vo->object));
+ l += column_qname (*id_member (*vo->obj));
}
else
{
@@ -3430,7 +3506,7 @@ namespace relational
l += "=";
l += quote_id (lt);
l += '.';
- l += column_qname (*id_member (*e.vo->object));
+ l += column_qname (*id_member (*e.vo->obj));
}
}
}
@@ -3442,7 +3518,7 @@ namespace relational
//
l = quote_id (lt);
l += '.';
- l += column_qname (*id_member (*e.vo->object));
+ l += column_qname (*id_member (*e.vo->obj));
l += " = ";
l += quote_id (rt);
l += '.';
@@ -3458,7 +3534,7 @@ namespace relational
l += " = ";
l += quote_id (rt);
l += '.';
- l += column_qname (*id_member (*vo->object));
+ l += column_qname (*id_member (*vo->obj));
}
}