From a26f4251e67ccaaaa848982946c8867443092ebe Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 19 Aug 2011 14:08:16 +0200 Subject: Rework query machinery not to use '_' as primary table alias Now we always qualify with the actual table name and use the '_' alias for situations where an object is referencing itself. --- odb/relational/common.cxx | 15 ++++++--- odb/relational/common.hxx | 1 + odb/relational/mysql/source.cxx | 4 +-- odb/relational/source.hxx | 75 +++++++++++++++++++++++++++++------------ 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx index 6032548..2a4a461 100644 --- a/odb/relational/common.cxx +++ b/odb/relational/common.cxx @@ -29,7 +29,7 @@ namespace relational : ptr_ (true), decl_ (false) { scope_ = "access::object_traits< " + c.fq_name () + " >::query_columns"; - table_ = table_qname (c); + table_ = default_table_ = table_qname (c); } void query_columns:: @@ -153,15 +153,20 @@ namespace relational } else { - // Use the default table alias unless we are generating members + // Leave the default table name unless we are generating members // for a referenced object. // string column; if (!ptr_) - column = table_; - else - column = "_"; + { + // If this is a self-reference, use the special '_' alias. + // + if (table_ != default_table_) + column = table_; + else + column = "_"; + } column += '.'; column += quote_id (col_name); diff --git a/odb/relational/common.hxx b/odb/relational/common.hxx index eed2234..1413e3f 100644 --- a/odb/relational/common.hxx +++ b/odb/relational/common.hxx @@ -82,6 +82,7 @@ namespace relational string scope_; string table_; + string default_table_; }; // diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx index e40a40a..451a44d 100644 --- a/odb/relational/mysql/source.cxx +++ b/odb/relational/mysql/source.cxx @@ -122,7 +122,7 @@ namespace relational if (!table.empty ()) { - line_ += table == table_name_ ? "_" : table; + line_ += table; line_ += '.'; } @@ -131,7 +131,7 @@ namespace relational if (!table.empty ()) { - line_ += table == table_name_ ? "_" : table; + line_ += table; line_ += '.'; } diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 741b97d..d30f605 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -127,9 +127,7 @@ namespace relational { if (!table.empty ()) { - // Use alias for the main table. - // - line_ += table == table_name_ ? "_" : table; + line_ += table; line_ += '.'; } @@ -187,6 +185,13 @@ namespace relational string line (" LEFT JOIN "); line += i->table; + + // If this is a self-join, alias it as '_' to resolve any + // ambiguities. + // + if (i->table == table_) + line += " AS _"; + line += " ON "; for (conditions::iterator b (i->cond.begin ()), j (b); @@ -225,17 +230,26 @@ namespace relational t = table_qname (*im, tp); string const& val (column_qname (*im, "value", "value")); - cond << t << '.' << val << " = _." << column_qname (id_); + cond << t << '.' << val << " = " << + table_ << "." << column_qname (id_); // Add the join for the object itself so that we are able to // use it in the WHERE clause. // if (query_) { - dt = ct; + dt = quote_id (ct); string const& id (column_qname (*im, "id", "object_id")); - dcond << dt << '.' << column_qname (*id_member (*c)) << " = " << + // If this is a self-join, use the '_' alias instead of the + // table name. + // + if (dt == table_) + dcond << "_"; + else + dcond << dt; + + dcond << '.' << column_qname (*id_member (*c)) << " = " << t << '.' << id; } } @@ -243,8 +257,16 @@ namespace relational { t = table_qname (*c); - cond << t << '.' << column_qname (*im) << " = _." << - column_qname (id_); + // If this is a self-join, use the '_' alias instead of the + // table name. + // + if (t == table_) + cond << "_"; + else + cond << t; + + cond << '.' << column_qname (*im) << " = " << + table_ << "." << column_qname (id_); } } else if (query_) @@ -254,8 +276,16 @@ namespace relational // t = table_qname (*c); - cond << t << '.' << column_qname (*id_member (*c)) << " = _." << - quote_id (col_name); + // If this is a self-join, use the '_' alias instead of the + // table name. + // + if (t == table_) + cond << "_"; + else + cond << t; + + cond << '.' << column_qname (*id_member (*c)) << " = " << + table_ << "." << quote_id (col_name); } if (!t.empty ()) @@ -712,17 +742,18 @@ namespace relational instance qp; os << strlit ("SELECT ") << endl - << strlit ("_." + inv_fid + ',') << endl - << strlit ("_." + inv_id) << endl - << strlit (" FROM " + inv_table + " AS _" - " WHERE _." + inv_fid + "=" + qp->next ()); + << strlit (inv_table + "." + inv_fid + ',') << endl + << strlit (inv_table + "." + inv_id) << endl + << strlit (" FROM " + inv_table + + " WHERE " + inv_table + "." + inv_fid + "=" + + qp->next ()); } else { string const& id_col (column_qname (m, "id", "object_id")); os << strlit ("SELECT ") << endl - << strlit ("_." + id_col + ',') << endl; + << strlit (table + "." + id_col + ',') << endl; switch (ck) { @@ -772,15 +803,16 @@ namespace relational instance qp; - os << strlit (" FROM " + table + " AS _" - " WHERE _." + id_col + "=" + qp->next ()); + os << strlit (" FROM " + table + + " WHERE " + table + "." + id_col + "=" + + qp->next ()); if (ordered) { string const& col (column_qname (m, "index", "index")); os << endl - << strlit (" ORDER BY _." + col) << endl; + << strlit (" ORDER BY " + table + "." + col) << endl; } } @@ -2077,7 +2109,7 @@ namespace relational instance t (table, true); t->traverse (c); - os << strlit (" FROM " + table + " AS _") << endl; + os << strlit (" FROM " + table) << endl; bool f (false); instance j (c, f); // @@ (im)perfect forwarding @@ -2085,7 +2117,8 @@ namespace relational j->write (); instance qp; - os << strlit (" WHERE _." + id_col + "=" + qp->next ()) << ";" + os << strlit (" WHERE " + table + "." + id_col + "=" + + qp->next ()) << ";" << endl; } @@ -2133,7 +2166,7 @@ namespace relational oc->traverse (c); } - os << strlit (" FROM " + table + " AS _") << endl; + os << strlit (" FROM " + table) << endl; oj->write (); os << strlit (" ") << ";" << endl; -- cgit v1.1