From 6e3ac760696d4ec43138b1aba82426582c767072 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/pgsql/query.cxx | 155 ++++++++++++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 72 deletions(-) (limited to 'odb/pgsql/query.cxx') diff --git a/odb/pgsql/query.cxx b/odb/pgsql/query.cxx index 1c5f9d4..856c031 100644 --- a/odb/pgsql/query.cxx +++ b/odb/pgsql/query.cxx @@ -28,7 +28,6 @@ namespace odb query (const query& q) : clause_ (q.clause_), parameters_ (q.parameters_), - parameter_offsets_ (q.parameter_offsets_), bind_ (q.bind_), binding_ (0, 0), values_ (q.values_), @@ -70,7 +69,6 @@ namespace odb { clause_ = q.clause_; parameters_ = q.parameters_; - parameter_offsets_ = q.parameter_offsets_; bind_ = q.bind_; size_t n (bind_.size ()); @@ -108,56 +106,7 @@ namespace odb query& query:: operator+= (const query& q) { - size_t cur_pos (0); - - // Append the argument clause to the clause of this instance. - // - for (size_t i (0), - p (parameters_.size () + 1), - e (q.parameter_offsets_.size ()); - i < e; - ++i, ++p) - { - size_t n (clause_.size ()); - - if (n != 0 && clause_[n - 1] != ' ' && q.clause_[cur_pos] != ' ') - clause_ += ' '; - - parameter_offset o (q.parameter_offsets_[i]); - - // Append all characters up to the start of the current - // parameter specifier, including the '$'. - // - clause_.append (q.clause_, cur_pos, o.first - cur_pos + 1); - - // Advance current position in source clause to 1 element past - // the current parameter specifier. - // - cur_pos = o.second; - - // Insert the correct parameter number and update the parameter - // offset to describe its offset in the new clause. - // - o.first = clause_.size () - 1; - ostringstream os; - os << p; - clause_.append (os.str ()); - o.second = clause_.size (); - - parameter_offsets_.push_back (o); - } - - // Copy any remaining characters in q.clause_. - // - if (cur_pos < q.clause_.size ()) - { - size_t n (clause_.size ()); - - if (n != 0 && clause_[n - 1] != ' ' && q.clause_[cur_pos] != ' ') - clause_ += ' '; - - clause_.append (q.clause_, cur_pos, string::npos); - } + clause_.insert (clause_.end (), q.clause_.begin (), q.clause_.end ()); size_t n (bind_.size ()); @@ -204,22 +153,34 @@ namespace odb } void query:: - add (details::shared_ptr p) + append (const string& q, clause_part::kind_type k) { - size_t n (clause_.size ()); + if (k == clause_part::native && + !clause_.empty () && + clause_.back ().kind == clause_part::native) + { + string& s (clause_.back ().part); - if (n != 0 && clause_[n - 1] != ' ') - clause_ += ' '; + char first (!q.empty () ? q[0] : ' '); + char last (!s.empty () ? s[s.size () - 1] : ' '); - parameter_offset o; - o.first = clause_.size (); + // We don't want extra spaces after '(' as well as before ',' + // and ')'. + // + if (last != ' ' && last != '(' && + first != ' ' && first != ',' && first != ')') + s += ' '; - ostringstream ss; - ss << parameters_.size () + 1; - clause_ += '$' + ss.str (); + s += q; + } + else + clause_.push_back (clause_part (k, q)); + } - o.second = clause_.size (); - parameter_offsets_.push_back (o); + void query:: + add (details::shared_ptr p) + { + clause_.push_back (clause_part (clause_part::param)); parameters_.push_back (p); bind_.push_back (bind ()); @@ -288,17 +249,67 @@ namespace odb return native_binding_; } - std::string query:: - clause () const + string query:: + clause (string const& table) const { - if (clause_.empty () || - clause_.compare (0, 6, "WHERE ") == 0 || - clause_.compare (0, 9, "ORDER BY ") == 0 || - clause_.compare (0, 9, "GROUP BY ") == 0 || - clause_.compare (0, 7, "HAVING ") == 0) - return clause_; + string r; + size_t param (1); + + for (clause_type::const_iterator i (clause_.begin ()), + end (clause_.end ()); i != end; ++i) + { + char last (!r.empty () ? r[r.size () - 1] : ' '); + + switch (i->kind) + { + case clause_part::column: + { + if (last != ' ' && last != '(') + r += ' '; + + if (i->part[0] == '.') + r += table; + + r += i->part; + break; + } + case clause_part::param: + { + if (last != ' ' && last != '(') + r += ' '; + + ostringstream os; + os << param++; + r += '$'; + r += os.str (); + break; + } + case clause_part::native: + { + // We don't want extra spaces after '(' as well as before ',' + // and ')'. + // + const string& p (i->part); + char first (!p.empty () ? p[0] : ' '); + + if (last != ' ' && last != '(' && + first != ' ' && first != ',' && first != ')') + r += ' '; + + r += p; + break; + } + } + } + + if (r.empty () || + r.compare (0, 6, "WHERE ") == 0 || + r.compare (0, 9, "ORDER BY ") == 0 || + r.compare (0, 9, "GROUP BY ") == 0 || + r.compare (0, 7, "HAVING ") == 0) + return r; else - return "WHERE " + clause_; + return "WHERE " + r; } } } -- cgit v1.1