diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2012-11-21 13:11:43 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2012-11-21 13:11:43 +0200 |
commit | 4d51a8a248bcbe50849b6c7682aaca1aa9ebff98 (patch) | |
tree | 968edd20009ec455ed54c072820c9a338eaa1988 /odb/pgsql/query-dynamic.cxx | |
parent | 2eac10b0aae159bdfc249c67f11b32a65036352d (diff) |
Add dynamic multi-database query support
Diffstat (limited to 'odb/pgsql/query-dynamic.cxx')
-rw-r--r-- | odb/pgsql/query-dynamic.cxx | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/odb/pgsql/query-dynamic.cxx b/odb/pgsql/query-dynamic.cxx new file mode 100644 index 0000000..8e3ae71 --- /dev/null +++ b/odb/pgsql/query-dynamic.cxx @@ -0,0 +1,136 @@ +// file : odb/pgsql/query-dynamic.cxx +// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cstddef> // std::size_t + +#include <odb/pgsql/query-dynamic.hxx> + +using namespace std; + +namespace odb +{ + namespace pgsql + { + static const char* logic_operators[] = {") AND (", ") OR ("}; + static const char* comp_operators[] = {"=", "!=", "<", ">", "<=", ">="}; + + static void + translate (query_base& q, const odb::query_base& s, size_t p) + { + typedef odb::query_base::clause_part part; + + const part& x (s.clause ()[p]); + + switch (x.kind) + { + case part::kind_column: + { + const query_column_base* c ( + static_cast<const query_column_base*> ( + x.native_info[id_pgsql].column)); + + q.append (c->table (), c->column ()); + break; + } + case part::kind_param_val: + case part::kind_param_ref: + { + const query_column_base* c ( + static_cast<const query_column_base*> ( + x.native_info[id_pgsql].column)); + + query_param_factory f ( + reinterpret_cast<query_param_factory> ( + x.native_info[id_pgsql].param_factory)); + + const odb::query_param* p ( + reinterpret_cast<const odb::query_param*> (x.data)); + + q.append (f (p->value, x.kind == part::kind_param_ref), + c->conversion ()); + break; + } + case part::kind_native: + { + q.append (s.strings ()[x.data]); + break; + } + case part::kind_true: + case part::kind_false: + { + q.append (x.kind == part::kind_true); + break; + } + case part::op_add: + { + translate (q, s, x.data); + translate (q, s, p - 1); + break; + } + case part::op_and: + case part::op_or: + { + q += "("; + translate (q, s, x.data); + q += logic_operators[x.kind - part::op_and]; + translate (q, s, p - 1); + q += ")"; + break; + } + case part::op_not: + { + q += "NOT ("; + translate (q, s, p - 1); + q += ")"; + break; + } + case part::op_null: + case part::op_not_null: + { + translate (q, s, p - 1); + q += (x.kind == part::op_null ? "IS NULL" : "IS NOT NULL"); + break; + } + case part::op_in: + { + size_t b (p - x.data); + + translate (q, s, b - 1); // column + q += "IN ("; + + for (size_t i (b); i != p; ++i) + { + if (i != b) + q += ","; + + translate (q, s, i); + } + + q += ")"; + break; + } + case part::op_eq: + case part::op_ne: + case part::op_lt: + case part::op_gt: + case part::op_le: + case part::op_ge: + { + translate (q, s, x.data); + q += comp_operators[x.kind - part::op_eq]; + translate (q, s, p - 1); + break; + } + } + } + + query_base:: + query_base (const odb::query_base& q) + : binding_ (0, 0), native_binding_ (0, 0, 0, 0) + { + if (!q.empty ()) + translate (*this, q, q.clause ().size () - 1); + } + } +} |