From a7bd7367e246ec5b6bb2e2f018a05173ff7e6301 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 27 Sep 2011 11:20:31 +0200 Subject: Add support for associating tables with views --- odb/relational/header.hxx | 26 ++++++--- odb/relational/inline.hxx | 4 +- odb/relational/processor.cxx | 52 +++++++++++++---- odb/relational/source.cxx | 4 +- odb/relational/source.hxx | 136 +++++++++++++++++++++++++++++++++---------- 5 files changed, 170 insertions(+), 52 deletions(-) (limited to 'odb/relational') 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 ("object-count")); + + if (obj_count != 0) { view_objects& objs (c.get ("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 ("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 ("object-count")); + + if (obj_count != 0) { view_objects& objs (c.get ("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)); } } -- cgit v1.1