summaryrefslogtreecommitdiff
path: root/odb/sqlite/query.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/sqlite/query.cxx')
-rw-r--r--odb/sqlite/query.cxx378
1 files changed, 0 insertions, 378 deletions
diff --git a/odb/sqlite/query.cxx b/odb/sqlite/query.cxx
deleted file mode 100644
index 98eb1cd..0000000
--- a/odb/sqlite/query.cxx
+++ /dev/null
@@ -1,378 +0,0 @@
-// file : odb/sqlite/query.cxx
-// license : GNU GPL v2; see accompanying LICENSE file
-
-#include <cstddef> // std::size_t
-#include <cstring> // std::memset
-
-#include <odb/sqlite/query.hxx>
-
-using namespace std;
-
-namespace odb
-{
- namespace sqlite
- {
- // query_param
- //
-
- query_param::
- ~query_param ()
- {
- }
-
- // query_params
- //
-
- query_params::
- query_params (const query_params& x)
- : details::shared_base (x),
- params_ (x.params_), bind_ (x.bind_), binding_ (0, 0)
- {
- // Here and below we want to maintain up to date binding info so
- // that the call to binding() below is an immutable operation,
- // provided the query does not have any by-reference parameters.
- // This way a by-value-only query can be shared between multiple
- // threads without the need for synchronization.
- //
- if (size_t n = bind_.size ())
- {
- binding_.bind = &bind_[0];
- binding_.count = n;
- binding_.version++;
- }
- }
-
- query_params& query_params::
- operator= (const query_params& x)
- {
- if (this != &x)
- {
- params_ = x.params_;
- bind_ = x.bind_;
-
- size_t n (bind_.size ());
- binding_.bind = n != 0 ? &bind_[0] : 0;
- binding_.count = n;
- binding_.version++;
- }
-
- return *this;
- }
-
- query_params& query_params::
- operator+= (const query_params& x)
- {
- size_t n (bind_.size ());
-
- params_.insert (params_.end (), x.params_.begin (), x.params_.end ());
- bind_.insert (bind_.end (), x.bind_.begin (), x.bind_.end ());
-
- if (n != bind_.size ())
- {
- binding_.bind = &bind_[0];
- binding_.count = bind_.size ();
- binding_.version++;
- }
-
- return *this;
- }
-
- void query_params::
- add (details::shared_ptr<query_param> p)
- {
- params_.push_back (p);
- bind_.push_back (sqlite::bind ());
- binding_.bind = &bind_[0];
- binding_.count = bind_.size ();
- binding_.version++;
-
- sqlite::bind* b (&bind_.back ());
- memset (b, 0, sizeof (sqlite::bind));
- p->bind (b);
- }
-
- void query_params::
- init ()
- {
- bool inc_ver (false);
-
- for (size_t i (0); i < params_.size (); ++i)
- {
- query_param& p (*params_[i]);
-
- if (p.reference ())
- {
- if (p.init ())
- {
- p.bind (&bind_[i]);
- inc_ver = true;
- }
- }
- }
-
- if (inc_ver)
- binding_.version++;
- }
-
- // query_base
- //
-
- query_base::
- query_base (const query_base& q)
- : clause_ (q.clause_),
- parameters_ (new (details::shared) query_params (*q.parameters_))
- {
- }
-
- query_base& query_base::
- operator= (const query_base& q)
- {
- if (this != &q)
- {
- clause_ = q.clause_;
- *parameters_ = *q.parameters_;
- }
-
- return *this;
- }
-
- query_base& query_base::
- operator+= (const query_base& q)
- {
- clause_.insert (clause_.end (), q.clause_.begin (), q.clause_.end ());
- *parameters_ += *q.parameters_;
- return *this;
- }
-
- void query_base::
- append (const string& q)
- {
- if (!clause_.empty () &&
- clause_.back ().kind == clause_part::kind_native)
- {
- string& s (clause_.back ().part);
-
- char first (!q.empty () ? q[0] : ' ');
- char last (!s.empty () ? s[s.size () - 1] : ' ');
-
- // We don't want extra spaces after '(' as well as before ','
- // and ')'.
- //
- if (last != ' ' && last != '\n' && last != '(' &&
- first != ' ' && first != '\n' && first != ',' && first != ')')
- s += ' ';
-
- s += q;
- }
- else
- clause_.push_back (clause_part (clause_part::kind_native, q));
- }
-
- void query_base::
- append (const char* table, const char* column)
- {
- string s (table);
- s += '.';
- s += column;
-
- clause_.push_back (clause_part (clause_part::kind_column, s));
- }
-
- void query_base::
- append (details::shared_ptr<query_param> p, const char* conv)
- {
- clause_.push_back (clause_part (clause_part::kind_param));
-
- if (conv != 0)
- clause_.back ().part = conv;
-
- parameters_->add (p);
- }
-
- static bool
- check_prefix (const string& s)
- {
- string::size_type n;
-
- // It is easier to compare to upper and lower-case versions
- // rather than getting involved with the portable case-
- // insensitive string comparison mess.
- //
- if (s.compare (0, (n = 5), "WHERE") == 0 ||
- s.compare (0, (n = 5), "where") == 0 ||
- s.compare (0, (n = 6), "SELECT") == 0 ||
- s.compare (0, (n = 6), "select") == 0 ||
- s.compare (0, (n = 8), "ORDER BY") == 0 ||
- s.compare (0, (n = 8), "order by") == 0 ||
- s.compare (0, (n = 8), "GROUP BY") == 0 ||
- s.compare (0, (n = 8), "group by") == 0 ||
- s.compare (0, (n = 6), "HAVING") == 0 ||
- s.compare (0, (n = 6), "having") == 0 ||
- s.compare (0, (n = 4), "WITH") == 0 ||
- s.compare (0, (n = 4), "with") == 0 ||
- s.compare (0, (n = 6), "PRAGMA") == 0 ||
- s.compare (0, (n = 6), "pragma") == 0)
- {
- // It either has to be an exact match, or there should be
- // a whitespace following the keyword.
- //
- if (s.size () == n || s[n] == ' ' || s[n] == '\n' || s[n] =='\t')
- return true;
- }
-
- return false;
- }
-
- void query_base::
- optimize ()
- {
- // Remove a single TRUE literal or one that is followe by one of
- // the other clauses. This avoids useless WHERE clauses like
- //
- // WHERE TRUE GROUP BY foo
- //
- clause_type::iterator i (clause_.begin ()), e (clause_.end ());
-
- if (i != e && i->kind == clause_part::kind_bool && i->bool_part)
- {
- clause_type::iterator j (i + 1);
-
- if (j == e ||
- (j->kind == clause_part::kind_native && check_prefix (j->part)))
- clause_.erase (i);
- }
- }
-
- const char* query_base::
- clause_prefix () const
- {
- if (!clause_.empty ())
- {
- const clause_part& p (clause_.front ());
-
- if (p.kind == clause_part::kind_native && check_prefix (p.part))
- return "";
-
- return "WHERE ";
- }
-
- return "";
- }
-
- string query_base::
- clause () const
- {
- 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::kind_column:
- {
- if (last != ' ' && last != '\n' && last != '(')
- r += ' ';
-
- r += i->part;
- break;
- }
- case clause_part::kind_param:
- {
- if (last != ' ' && last != '\n' && last != '(')
- r += ' ';
-
- // Add the conversion expression, if any.
- //
- string::size_type p (0);
- if (!i->part.empty ())
- {
- p = i->part.find ("(?)");
- r.append (i->part, 0, p);
- }
-
- r += '?';
-
- if (!i->part.empty ())
- r.append (i->part, p + 3, string::npos);
-
- break;
- }
- case clause_part::kind_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 != ' ' && first != '\n' && last != '(' &&
- first != ' ' && last != '\n' && first != ',' && first != ')')
- r += ' ';
-
- r += p;
- break;
- }
- case clause_part::kind_bool:
- {
- if (last != ' ' && last != '\n' && last != '(')
- r += ' ';
-
- r += i->bool_part ? "1" : "0";
- break;
- }
- }
- }
-
- return clause_prefix () + r;
- }
-
- query_base
- operator&& (const query_base& x, const query_base& y)
- {
- // Optimize cases where one or both sides are constant truth.
- //
- bool xt (x.const_true ()), yt (y.const_true ());
-
- if (xt && yt)
- return x;
-
- if (xt)
- return y;
-
- if (yt)
- return x;
-
- query_base r ("(");
- r += x;
- r += ") AND (";
- r += y;
- r += ")";
- return r;
- }
-
- query_base
- operator|| (const query_base& x, const query_base& y)
- {
- query_base r ("(");
- r += x;
- r += ") OR (";
- r += y;
- r += ")";
- return r;
- }
-
- query_base
- operator! (const query_base& x)
- {
- query_base r ("NOT (");
- r += x;
- r += ")";
- return r;
- }
- }
-}