diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-06 08:57:30 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-02-06 08:57:30 +0200 |
commit | f5e457f5dee11cbd20fc3557f79d6e1f235fb89f (patch) | |
tree | 17b21ea5494e37aea6a336284990ebb6424466e8 /odb/relational/source.cxx | |
parent | 2ca4828d303fdd27c573429910f7a25fd1e3727c (diff) |
Implement join types support in views
Diffstat (limited to 'odb/relational/source.cxx')
-rw-r--r-- | odb/relational/source.cxx | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index dc083bb..e0fbab3 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -4776,12 +4776,19 @@ traverse_view (type& c) continue; } - l = "LEFT JOIN "; + l = join_syntax (*i); + l += ' '; l += quote_id (i->tbl_name); if (!i->alias.empty ()) l += (need_alias_as ? " AS " : " ") + quote_id (i->alias); + if (i->join == view_object::cross) // No ON condition for CROSS JOIN. + { + from.push_back (l); + continue; + } + semantics::scope& scope ( dynamic_cast<semantics::scope&> (*unit.find (i->scope))); @@ -4851,20 +4858,28 @@ traverse_view (type& c) semantics::scope& scope ( dynamic_cast<semantics::scope&> (*unit.find (i->scope))); - expression e ( - translate_expression ( - c, i->cond, scope, i->loc, "object")); + expression e (i->join == view_object::cross + ? expression ("") // Dummy literal expression. + : translate_expression ( + c, i->cond, scope, i->loc, "object")); // Literal expression. // if (e.kind == expression::literal) { - l = "LEFT JOIN "; + l = join_syntax (*i); + l += ' '; l += table_qname (o); if (!alias.empty ()) l += (need_alias_as ? " AS " : " ") + quote_id (alias); + if (i->join == view_object::cross) // No ON condition for CROSS JOIN. + { + from.push_back (l); + continue; + } + l += " ON"; // Add the pragma location for easier error tracking. @@ -4891,6 +4906,9 @@ traverse_view (type& c) // is a to-many relationship, then we first need to JOIN the // container table. This code is similar to object_joins. // + // Note that this cannot be CROSS JOIN; we've handled that case + // above. + // using semantics::data_member; data_member& m (*e.member_path.back ()); @@ -5029,7 +5047,8 @@ traverse_view (type& c) string ct; // Container table. if (cont != 0) { - l = "LEFT JOIN "; + l = join_syntax (*i); + l += ' '; // The same relationship can be used by multiple associated // objects. So if the object that contains this container has @@ -5174,7 +5193,15 @@ traverse_view (type& c) } } - l = "LEFT JOIN "; + // If we have already joined the container with the desired + // join type, then use LEFT JOIN to join the object to the + // container. This is the right thing to do since an entry + // in the container can only point (either via id or value) + // to a single object. + // + l = (cont == 0 ? join_syntax (*i) : "LEFT JOIN"); + l += ' '; + l += table_qname (o); if (!alias.empty ()) @@ -5563,13 +5590,36 @@ traverse_view (type& c) { if (i->compare (0, 5, "FROM ") == 0) os << "r += " << strlit (*i) << ";"; - else if (i->compare (0, 5, "LEFT ") == 0) - os << endl - << "r += " << strlit (sep + *i) << ";"; else if (i->compare (0, 3, "// ") == 0) os << *i << endl; else - os << "r += " << *i << ";"; // Already a string literal. + { + // See if this is a JOIN. The exact spelling is database-dependent, + // but we know there is the JOIN word in there somewhere and before + // it we should only have keywords and spaces. + // + size_t p (i->find ("JOIN ")); + if (p != string::npos) + { + // Make sure before it we only have A-Z and spaces. + // + for (char c; p != 0; --p) + { + c = (*i)[p - 1]; + if ((c < 'A' || c > 'Z') && c != ' ') + break; + } + + if (p == 0) + os << endl + << "r += " << strlit (sep + *i) << ";"; + } + + // Something else, assume already a string literal. + // + if (p != 0) + os << "r += " << *i << ";"; + } } // Generate the query condition. |