From e68f09c0e8c747474745f3438496e9352a199dbd Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 21 Nov 2012 13:11:43 +0200 Subject: Add dynamic multi-database query support --- odb/query-dynamic.cxx | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 odb/query-dynamic.cxx (limited to 'odb/query-dynamic.cxx') diff --git a/odb/query-dynamic.cxx b/odb/query-dynamic.cxx new file mode 100644 index 0000000..96aefab --- /dev/null +++ b/odb/query-dynamic.cxx @@ -0,0 +1,182 @@ +// file : odb/query-dynamic.cxx +// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +using namespace std; + +namespace odb +{ + // query_param + // + query_param:: + ~query_param () + { + } + + // query_base + // + void query_base:: + clear () + { + for (clause_type::iterator i (clause_.begin ()); i != clause_.end (); ++i) + { + if (i->kind == clause_part::kind_param_val || + i->kind == clause_part::kind_param_ref) + { + query_param* qp (reinterpret_cast (i->data)); + + if (qp != 0 && qp->_dec_ref ()) + delete qp; + } + } + + clause_.clear (); + strings_.clear (); + } + + void query_base:: + append (const string& native) + { + strings_.push_back (native); + clause_.push_back (clause_part ()); + clause_.back ().kind = clause_part::kind_native; + clause_.back ().data = strings_.size () - 1; + } + + void query_base:: + append (const query_base& x) + { + size_t i (clause_.size ()), delta (i); + size_t n (i + x.clause_.size ()); + clause_.resize (n); + + for (size_t j (0); i < n; ++i, ++j) + { + const clause_part& s (x.clause_[j]); + clause_part& d (clause_[i]); + + d = s; + + // We need to increment the param references, update pointers + // to strings and update argument positions. + // + switch (s.kind) + { + case clause_part::kind_param_val: + case clause_part::kind_param_ref: + { + reinterpret_cast (d.data)->_inc_ref (); + break; + } + case clause_part::kind_native: + { + strings_.push_back (x.strings_[s.data]); + d.data = strings_.size () - 1; + break; + } + case clause_part::op_eq: + case clause_part::op_and: + { + d.data += delta; + break; + } + default: + break; + } + } + } + + void query_base:: + append_ref (const void* ref, const native_column_info* c) + { + clause_.push_back (clause_part ()); + clause_part& p (clause_.back ()); + + p.kind = clause_part::kind_param_ref; + p.data = 0; // In case new below throws. + p.native_info = c; + + p.data = reinterpret_cast ( + new (details::shared) query_param (ref)); + } + + query_base& query_base:: + operator+= (const std::string& native) + { + if (!native.empty ()) + { + size_t p (clause_.size ()); + append (native); + + if (p != 0) + append (clause_part::op_add, p - 1); + } + + return *this; + } + + query_base& query_base:: + operator+= (const query_base& x) + { + if (!x.empty ()) + { + size_t p (clause_.size ()); + append (x); + + if (p != 0) + append (clause_part::op_add, p - 1); + } + + return *this; + } + + 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 || x.empty ()) + return y; + + if (yt || y.empty ()) + return x; + + query_base r (x); + r.append (y); + r.append (query_base::clause_part::op_and, x.clause ().size () - 1); + return r; + } + + query_base + operator|| (const query_base& x, const query_base& y) + { + if (x.empty ()) + return y; + + if (y.empty ()) + return x; + + query_base r (x); + r.append (y); + r.append (query_base::clause_part::op_or, x.clause ().size () - 1); + return r; + } + + query_base + operator! (const query_base& x) + { + if (x.empty ()) + return x; + + query_base r (x); + r.append (query_base::clause_part::op_not, 0); + return r; + } +} -- cgit v1.1