From 47d344f31f7a1a980d807c142e0a36b09db3b1f3 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/mysql/query.cxx | 104 +++++++++++++++++++++++++++++++++++++++++----------- odb/mysql/query.hxx | 96 ++++++++++++++++++++++++++++++------------------ odb/mysql/query.txx | 16 ++++---- 3 files changed, 151 insertions(+), 65 deletions(-) diff --git a/odb/mysql/query.cxx b/odb/mysql/query.cxx index e5c1705..ca858b1 100644 --- a/odb/mysql/query.cxx +++ b/odb/mysql/query.cxx @@ -63,15 +63,9 @@ namespace odb query& query:: operator+= (const query& q) { - size_t n (clause_.size ()); + clause_.insert (clause_.end (), q.clause_.begin (), q.clause_.end ()); - if (n != 0 && clause_[n - 1] != ' ' && - !q.clause_.empty () && q.clause_[0] != ' ') - clause_ += ' '; - - clause_ += q.clause_; - - n = bind_.size (); + size_t n (bind_.size ()); parameters_.insert ( parameters_.end (), q.parameters_.begin (), q.parameters_.end ()); @@ -90,14 +84,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] : ' '); - clause_ += '?'; + // We don't want extra spaces after '(' as well as before ',' + // and ')'. + // + if (last != ' ' && last != '(' && + first != ' ' && first != ',' && first != ')') + s += ' '; + + s += q; + } + else + clause_.push_back (clause_part (k, q)); + } + + void query:: + add (details::shared_ptr p) + { + clause_.push_back (clause_part (clause_part::param)); parameters_.push_back (p); bind_.push_back (MYSQL_BIND ()); @@ -142,17 +156,63 @@ namespace odb return r; } - 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; + + 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 += ' '; + + r += '?'; + 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; } } } diff --git a/odb/mysql/query.hxx b/odb/mysql/query.hxx index 8f2737b..0fea50c 100644 --- a/odb/mysql/query.hxx +++ b/odb/mysql/query.hxx @@ -85,15 +85,33 @@ namespace odb class LIBODB_MYSQL_EXPORT query { public: + struct clause_part + { + enum kind_type + { + column, + param, + native + }; + + clause_part (kind_type k): kind (k) {} + clause_part (kind_type k, const std::string& p): kind (k), part (p) {} + + kind_type kind; + std::string part; + }; + query () : binding_ (0, 0) { } explicit - query (const std::string& q) - : clause_ (q), binding_ (0, 0) + query (const std::string& q, + clause_part::kind_type k = clause_part::native) + : binding_ (0, 0) { + clause_.push_back (clause_part (k, q)); } template @@ -122,7 +140,7 @@ namespace odb public: std::string - clause () const; + clause (std::string const& default_table) const; binding& parameters_binding () const; @@ -149,12 +167,7 @@ namespace odb query& operator+= (const std::string& q) { - size_t n (clause_.size ()); - - if (n != 0 && clause_[n - 1] != ' ' && !q.empty () && q[0] != ' ') - clause_ += ' '; - - clause_ += q; + append (q, clause_part::native); return *this; } @@ -183,14 +196,18 @@ namespace odb void append (ref_bind); + void + append (const std::string&, clause_part::kind_type); + private: void add (details::shared_ptr); private: + typedef std::vector clause_type; typedef std::vector > parameters_type; - std::string clause_; + clause_type clause_; parameters_type parameters_; mutable std::vector bind_; mutable binding binding_; @@ -365,7 +382,7 @@ namespace odb query is_null () const { - query q (name_); + query q (name_, query::clause_part::column); q += "IS NULL"; return q; } @@ -373,7 +390,7 @@ namespace odb query is_not_null () const { - query q (name_); + query q (name_, query::clause_part::column); q += "IS NOT NULL"; return q; } @@ -409,7 +426,7 @@ namespace odb query equal (val_bind v) const { - query q (name_); + query q (name_, query::clause_part::column); q += "="; q.append (v); return q; @@ -426,7 +443,7 @@ namespace odb query equal (ref_bind r) const { - query q (name_); + query q (name_, query::clause_part::column); q += "="; q.append (r); return q; @@ -494,7 +511,7 @@ namespace odb query unequal (val_bind v) const { - query q (name_); + query q (name_, query::clause_part::column); q += "!="; q.append (v); return q; @@ -511,7 +528,7 @@ namespace odb query unequal (ref_bind r) const { - query q (name_); + query q (name_, query::clause_part::column); q += "!="; q.append (r); return q; @@ -579,7 +596,7 @@ namespace odb query less (val_bind v) const { - query q (name_); + query q (name_, query::clause_part::column); q += "<"; q.append (v); return q; @@ -596,7 +613,7 @@ namespace odb query less (ref_bind r) const { - query q (name_); + query q (name_, query::clause_part::column); q += "<"; q.append (r); return q; @@ -664,7 +681,7 @@ namespace odb query greater (val_bind v) const { - query q (name_); + query q (name_, query::clause_part::column); q += ">"; q.append (v); return q; @@ -681,7 +698,7 @@ namespace odb query greater (ref_bind r) const { - query q (name_); + query q (name_, query::clause_part::column); q += ">"; q.append (r); return q; @@ -749,7 +766,7 @@ namespace odb query less_equal (val_bind v) const { - query q (name_); + query q (name_, query::clause_part::column); q += "<="; q.append (v); return q; @@ -766,7 +783,7 @@ namespace odb query less_equal (ref_bind r) const { - query q (name_); + query q (name_, query::clause_part::column); q += "<="; q.append (r); return q; @@ -834,7 +851,7 @@ namespace odb query greater_equal (val_bind v) const { - query q (name_); + query q (name_, query::clause_part::column); q += ">="; q.append (v); return q; @@ -851,7 +868,7 @@ namespace odb query greater_equal (ref_bind r) const { - query q (name_); + query q (name_, query::clause_part::column); q += ">="; q.append (r); return q; @@ -918,9 +935,9 @@ namespace odb // (void) (sizeof (type_instance () == type_instance ())); - query q (name_); + query q (name_, query::clause_part::column); q += "="; - q += c.name (); + q.append (c.name (), query::clause_part::column); return q; } @@ -932,9 +949,9 @@ namespace odb // (void) (sizeof (type_instance () != type_instance ())); - query q (name_); + query q (name_, query::clause_part::column); q += "!="; - q += c.name (); + q.append (c.name (), query::clause_part::column); return q; } @@ -946,9 +963,9 @@ namespace odb // (void) (sizeof (type_instance () < type_instance ())); - query q (name_); + query q (name_, query::clause_part::column); q += "<"; - q += c.name (); + q.append (c.name (), query::clause_part::column); return q; } @@ -960,9 +977,9 @@ namespace odb // (void) (sizeof (type_instance () > type_instance ())); - query q (name_); + query q (name_, query::clause_part::column); q += ">"; - q += c.name (); + q.append (c.name (), query::clause_part::column); return q; } @@ -974,9 +991,9 @@ namespace odb // (void) (sizeof (type_instance () <= type_instance ())); - query q (name_); + query q (name_, query::clause_part::column); q += "<="; - q += c.name (); + q.append (c.name (), query::clause_part::column); return q; } @@ -988,9 +1005,9 @@ namespace odb // (void) (sizeof (type_instance () >= type_instance ())); - query q (name_); + query q (name_, query::clause_part::column); q += ">="; - q += c.name (); + q.append (c.name (), query::clause_part::column); return q; } @@ -1797,6 +1814,13 @@ namespace odb : object_traits::query_type (qc) { } + + std::string + clause () const + { + return object_traits::query_type::clause ( + object_traits::table_name); + } }; } diff --git a/odb/mysql/query.txx b/odb/mysql/query.txx index 8cbe201..6addb65 100644 --- a/odb/mysql/query.txx +++ b/odb/mysql/query.txx @@ -13,12 +13,14 @@ namespace odb template query:: query (const query_column& c) - : clause_ (c.name ()), binding_ (0, 0) + : binding_ (0, 0) { + clause_.push_back (clause_part (clause_part::column, c.name ())); + // Cannot use IS TRUE here since database type can be a non- // integral type. // - clause_ += " = "; + clause_.push_back (clause_part (clause_part::native, "=")); append (val_bind (true)); } @@ -28,7 +30,7 @@ namespace odb query query_column:: in (const T& v1, const T& v2) const { - query q (name_); + query q (name_, query::clause_part::column); q += "IN ("; q.append (val_bind (v1)); q += ","; @@ -41,7 +43,7 @@ namespace odb query query_column:: in (const T& v1, const T& v2, const T& v3) const { - query q (name_); + query q (name_, query::clause_part::column); q += "IN ("; q.append (val_bind (v1)); q += ","; @@ -56,7 +58,7 @@ namespace odb query query_column:: in (const T& v1, const T& v2, const T& v3, const T& v4) const { - query q (name_); + query q (name_, query::clause_part::column); q += "IN ("; q.append (val_bind (v1)); q += ","; @@ -73,7 +75,7 @@ namespace odb query query_column:: in (const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) const { - query q (name_); + query q (name_, query::clause_part::column); q += "IN ("; q.append (val_bind (v1)); q += ","; @@ -93,7 +95,7 @@ namespace odb query query_column:: in_range (I begin, I end) const { - query q (name_); + query q (name_, query::clause_part::column); q += "IN ("; for (I i (begin); i != end; ++i) -- cgit v1.1