summaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-09-27 11:20:31 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-09-27 11:20:31 +0200
commita7bd7367e246ec5b6bb2e2f018a05173ff7e6301 (patch)
tree41e796b972320267f35fce07b9c77fd82029b3e8 /odb/relational
parent8efcb4e093ec9faab36d49474fd3596a2ce90b13 (diff)
Add support for associating tables with views
Diffstat (limited to 'odb/relational')
-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
5 files changed, 170 insertions, 52 deletions
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));
}
}