aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-08-19 14:08:16 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-08-19 14:08:16 +0200
commit47d344f31f7a1a980d807c142e0a36b09db3b1f3 (patch)
treef139dc6f50bb9a8f89d075a23315cd19cc7d9ee3
parente4420208045f1bfb1a9c1fc726b4f6d1ae268f92 (diff)
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.
-rw-r--r--odb/mysql/query.cxx104
-rw-r--r--odb/mysql/query.hxx96
-rw-r--r--odb/mysql/query.txx16
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<query_param> 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<query_param> 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 <typename T>
@@ -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<T>);
+ void
+ append (const std::string&, clause_part::kind_type);
+
private:
void
add (details::shared_ptr<query_param>);
private:
+ typedef std::vector<clause_part> clause_type;
typedef std::vector<details::shared_ptr<query_param> > parameters_type;
- std::string clause_;
+ clause_type clause_;
parameters_type parameters_;
mutable std::vector<MYSQL_BIND> 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<T> v) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "=";
q.append<T, ID> (v);
return q;
@@ -426,7 +443,7 @@ namespace odb
query
equal (ref_bind<T> r) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "=";
q.append<T, ID> (r);
return q;
@@ -494,7 +511,7 @@ namespace odb
query
unequal (val_bind<T> v) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "!=";
q.append<T, ID> (v);
return q;
@@ -511,7 +528,7 @@ namespace odb
query
unequal (ref_bind<T> r) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "!=";
q.append<T, ID> (r);
return q;
@@ -579,7 +596,7 @@ namespace odb
query
less (val_bind<T> v) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "<";
q.append<T, ID> (v);
return q;
@@ -596,7 +613,7 @@ namespace odb
query
less (ref_bind<T> r) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "<";
q.append<T, ID> (r);
return q;
@@ -664,7 +681,7 @@ namespace odb
query
greater (val_bind<T> v) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += ">";
q.append<T, ID> (v);
return q;
@@ -681,7 +698,7 @@ namespace odb
query
greater (ref_bind<T> r) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += ">";
q.append<T, ID> (r);
return q;
@@ -749,7 +766,7 @@ namespace odb
query
less_equal (val_bind<T> v) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "<=";
q.append<T, ID> (v);
return q;
@@ -766,7 +783,7 @@ namespace odb
query
less_equal (ref_bind<T> r) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "<=";
q.append<T, ID> (r);
return q;
@@ -834,7 +851,7 @@ namespace odb
query
greater_equal (val_bind<T> v) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += ">=";
q.append<T, ID> (v);
return q;
@@ -851,7 +868,7 @@ namespace odb
query
greater_equal (ref_bind<T> r) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += ">=";
q.append<T, ID> (r);
return q;
@@ -918,9 +935,9 @@ namespace odb
//
(void) (sizeof (type_instance<T> () == type_instance<T2> ()));
- 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<T> () != type_instance<T2> ()));
- 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<T> () < type_instance<T2> ()));
- 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<T> () > type_instance<T2> ()));
- 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<T> () <= type_instance<T2> ()));
- 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<T> () >= type_instance<T2> ()));
- 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<T>::query_type (qc)
{
}
+
+ std::string
+ clause () const
+ {
+ return object_traits<T>::query_type::clause (
+ object_traits<T>::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 <database_type_id ID>
query::
query (const query_column<bool, ID>& 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<bool, ID> (val_bind<bool> (true));
}
@@ -28,7 +30,7 @@ namespace odb
query query_column<T, ID>::
in (const T& v1, const T& v2) const
{
- query q (name_);
+ query q (name_, query::clause_part::column);
q += "IN (";
q.append<T, ID> (val_bind<T> (v1));
q += ",";
@@ -41,7 +43,7 @@ namespace odb
query query_column<T, ID>::
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<T, ID> (val_bind<T> (v1));
q += ",";
@@ -56,7 +58,7 @@ namespace odb
query query_column<T, ID>::
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<T, ID> (val_bind<T> (v1));
q += ",";
@@ -73,7 +75,7 @@ namespace odb
query query_column<T, ID>::
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<T, ID> (val_bind<T> (v1));
q += ",";
@@ -93,7 +95,7 @@ namespace odb
query query_column<T, ID>::
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)