aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-11-21 13:11:43 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-11-21 13:11:43 +0200
commitb3826d5ff054deeb7ba22aecb242cec2dca2f93a (patch)
tree7af4d7b2742db8c36dda3c97d12a2c40bf4b14b0
parent83374c27062772de95ab12652713bfb2c218ba48 (diff)
Add dynamic multi-database query support
-rw-r--r--odb/oracle/exceptions.cxx10
-rw-r--r--odb/oracle/exceptions.hxx6
-rw-r--r--odb/oracle/makefile1
-rw-r--r--odb/oracle/query-dynamic.cxx142
-rw-r--r--odb/oracle/query-dynamic.hxx33
-rw-r--r--odb/oracle/query-dynamic.ixx73
-rw-r--r--odb/oracle/query-dynamic.txx26
-rw-r--r--odb/oracle/query.cxx2
-rw-r--r--odb/oracle/query.hxx160
-rw-r--r--odb/oracle/query.ixx4
-rw-r--r--odb/oracle/traits.hxx22
11 files changed, 413 insertions, 66 deletions
diff --git a/odb/oracle/exceptions.cxx b/odb/oracle/exceptions.cxx
index 87fc435..c8165cf 100644
--- a/odb/oracle/exceptions.cxx
+++ b/odb/oracle/exceptions.cxx
@@ -58,6 +58,16 @@ namespace odb
}
//
+ // lob_comparison
+ //
+
+ const char* lob_comparison::
+ what () const throw ()
+ {
+ return "comparison of LOB values in queries not supported";
+ }
+
+ //
// cli_exception
//
diff --git a/odb/oracle/exceptions.hxx b/odb/oracle/exceptions.hxx
index e9f41e8..73fb4c5 100644
--- a/odb/oracle/exceptions.hxx
+++ b/odb/oracle/exceptions.hxx
@@ -83,6 +83,12 @@ namespace odb
std::string what_;
};
+ struct LIBODB_ORACLE_EXPORT lob_comparison: odb::exception
+ {
+ virtual const char*
+ what () const throw ();
+ };
+
struct LIBODB_ORACLE_EXPORT cli_exception: odb::exception
{
cli_exception (const std::string& what);
diff --git a/odb/oracle/makefile b/odb/oracle/makefile
index 34fda85..1d5c835 100644
--- a/odb/oracle/makefile
+++ b/odb/oracle/makefile
@@ -15,6 +15,7 @@ exceptions.cxx \
oracle-types.cxx \
prepared-query.cxx \
query.cxx \
+query-dynamic.cxx \
query-const-expr.cxx \
simple-object-statements.cxx \
statement.cxx \
diff --git a/odb/oracle/query-dynamic.cxx b/odb/oracle/query-dynamic.cxx
new file mode 100644
index 0000000..5d8a2b7
--- /dev/null
+++ b/odb/oracle/query-dynamic.cxx
@@ -0,0 +1,142 @@
+// file : odb/oracle/query-dynamic.cxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#include <cstddef> // std::size_t
+
+#include <odb/oracle/query-dynamic.hxx>
+#include <odb/oracle/exceptions.hxx> // lob_comparison
+
+using namespace std;
+
+namespace odb
+{
+ namespace oracle
+ {
+ 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_oracle].column));
+
+ q.append (c->table (), c->column ());
+ break;
+ }
+ case part::kind_param_val:
+ case part::kind_param_ref:
+ {
+ const query_column_base& qc (
+ *static_cast<const query_column_base*> (
+ x.native_info[id_oracle].column));
+
+ query_param_factory f (
+ reinterpret_cast<query_param_factory> (
+ x.native_info[id_oracle].param_factory));
+
+ // If factory is NULL, then this is a LOB value.
+ //
+ if (f == 0)
+ throw lob_comparison ();
+
+ const odb::query_param* p (
+ reinterpret_cast<const odb::query_param*> (x.data));
+
+ q.append (f (p->value, qc, x.kind == part::kind_param_ref),
+ qc.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)
+ {
+ if (!q.empty ())
+ translate (*this, q, q.clause ().size () - 1);
+ }
+ }
+}
diff --git a/odb/oracle/query-dynamic.hxx b/odb/oracle/query-dynamic.hxx
new file mode 100644
index 0000000..e1b0229
--- /dev/null
+++ b/odb/oracle/query-dynamic.hxx
@@ -0,0 +1,33 @@
+// file : odb/oracle/query-dynamic.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_QUERY_DYNAMIC_HXX
+#define ODB_ORACLE_QUERY_DYNAMIC_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/query.hxx>
+#include <odb/query-dynamic.hxx>
+
+#include <odb/oracle/query.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ typedef details::shared_ptr<query_param> (*query_param_factory) (
+ const void* val, const query_column_base&, bool by_ref);
+
+ template <typename T, database_type_id ID>
+ details::shared_ptr<query_param>
+ query_param_factory_impl (const void*, const query_column_base&, bool);
+ }
+}
+
+#include <odb/oracle/query-dynamic.ixx>
+#include <odb/oracle/query-dynamic.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_QUERY_DYNAMIC_HXX
diff --git a/odb/oracle/query-dynamic.ixx b/odb/oracle/query-dynamic.ixx
new file mode 100644
index 0000000..4554921
--- /dev/null
+++ b/odb/oracle/query-dynamic.ixx
@@ -0,0 +1,73 @@
+// file : odb/oracle/query-dynamic.ixx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+namespace odb
+{
+ namespace oracle
+ {
+ //
+ //
+ template <typename T, database_type_id ID>
+ inline query_column<T, ID>::
+ query_column (odb::query_column<T>& qc,
+ const char* table,
+ const char* column,
+ const char* conv,
+ unsigned short prec,
+ short scale)
+ : query_column_base (table, column, conv, prec, scale)
+ {
+ native_column_info& ci (qc.native_info[id_oracle]);
+ ci.column = static_cast<query_column_base*> (this);
+
+ // For some reason GCC needs this statically-typed pointer in
+ // order to instantiate the functions.
+ //
+ query_param_factory f (&query_param_factory_impl<T, ID>);
+ ci.param_factory = reinterpret_cast<void*> (f);
+ }
+
+ template <typename T>
+ inline query_column<T, id_blob>::
+ query_column (odb::query_column<T>& qc,
+ const char* table, const char* column, const char*)
+ : lob_query_column (table, column)
+ {
+ native_column_info& ci (qc.native_info[id_oracle]);
+ ci.column = static_cast<query_column_base*> (this);
+
+ // In Oracle LOBs cannot be compared.
+ //
+ ci.param_factory = 0;
+ }
+
+ template <typename T>
+ inline query_column<T, id_clob>::
+ query_column (odb::query_column<T>& qc,
+ const char* table, const char* column, const char*)
+ : lob_query_column (table, column)
+ {
+ native_column_info& ci (qc.native_info[id_oracle]);
+ ci.column = static_cast<query_column_base*> (this);
+
+ // In Oracle LOBs cannot be compared.
+ //
+ ci.param_factory = 0;
+ }
+
+ template <typename T>
+ inline query_column<T, id_nclob>::
+ query_column (odb::query_column<T>& qc,
+ const char* table, const char* column, const char*)
+ : lob_query_column (table, column)
+ {
+ native_column_info& ci (qc.native_info[id_oracle]);
+ ci.column = static_cast<query_column_base*> (this);
+
+ // In Oracle LOBs cannot be compared.
+ //
+ ci.param_factory = 0;
+ }
+ }
+}
diff --git a/odb/oracle/query-dynamic.txx b/odb/oracle/query-dynamic.txx
new file mode 100644
index 0000000..7daebc4
--- /dev/null
+++ b/odb/oracle/query-dynamic.txx
@@ -0,0 +1,26 @@
+// file : odb/oracle/query-dynamic.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+namespace odb
+{
+ namespace oracle
+ {
+ template <typename T, database_type_id ID>
+ details::shared_ptr<query_param>
+ query_param_factory_impl (const void* val,
+ const query_column_base& qc,
+ bool by_ref)
+ {
+ const T& v (*static_cast<const T*> (val));
+
+ unsigned short p (qc.prec ());
+ short s (qc.scale ());
+
+ return details::shared_ptr<query_param> (
+ by_ref
+ ? new (details::shared) query_param_impl<T, ID> (ref_bind<T> (v, p, s))
+ : new (details::shared) query_param_impl<T, ID> (val_bind<T> (v, p, s)));
+ }
+ }
+}
diff --git a/odb/oracle/query.cxx b/odb/oracle/query.cxx
index b6b3018..1121b9d 100644
--- a/odb/oracle/query.cxx
+++ b/odb/oracle/query.cxx
@@ -120,7 +120,7 @@ namespace odb
}
void query_base::
- add (details::shared_ptr<query_param> p, const char* conv)
+ append (details::shared_ptr<query_param> p, const char* conv)
{
clause_.push_back (clause_part (clause_part::kind_param));
diff --git a/odb/oracle/query.hxx b/odb/oracle/query.hxx
index 9980833..1bf6853 100644
--- a/odb/oracle/query.hxx
+++ b/odb/oracle/query.hxx
@@ -11,6 +11,7 @@
#include <vector>
#include <cstddef> // std::size_t
+#include <odb/forward.hxx> // odb::query_column
#include <odb/query.hxx>
#include <odb/oracle/version.hxx>
@@ -136,7 +137,7 @@ namespace odb
query_base (bool v)
: binding_ (0, 0)
{
- clause_.push_back (clause_part (v));
+ append (v);
}
explicit
@@ -180,6 +181,13 @@ namespace odb
template <database_type_id ID>
query_base (const query_column<bool, ID>&);
+ // Translate common query representation to Oracle native. Defined
+ // in query-dynamic.cxx
+ //
+ query_base (const odb::query_base&);
+
+ // Copy c-tor and assignment.
+ //
query_base (const query_base&);
query_base&
@@ -264,24 +272,37 @@ namespace odb
return *this;
}
+ // Implementation details.
+ //
public:
template <typename T, database_type_id ID>
void
- append (val_bind<T>, const char* conv);
+ append (val_bind<T>, const char* conv);
template <typename T, database_type_id ID>
void
- append (ref_bind<T>, const char* conv);
+ append (ref_bind<T>, const char* conv);
+
+ void
+ append (details::shared_ptr<query_param>, const char* conv);
+
+ void
+ append (bool v)
+ {
+ clause_.push_back (clause_part (v));
+ }
void
append (const std::string& native);
void
- append (const char* table, const char* column);
+ append (const char* native) // Clashes with append(bool).
+ {
+ append (std::string (native));
+ }
- private:
void
- add (details::shared_ptr<query_param>, const char* conv);
+ append (const char* table, const char* column);
private:
typedef std::vector<clause_part> clause_type;
@@ -404,34 +425,18 @@ namespace odb
// query_column
//
-
- template <typename T, typename T2>
- class copy_bind: public val_bind<T>
- {
- public:
- explicit
- copy_bind (const T2& v): val_bind<T> (val), val (v) {}
-
- const T val;
- };
-
- template <typename T>
- const T&
- type_instance ();
-
- template <typename T, database_type_id ID>
- struct query_column
+ struct LIBODB_ORACLE_EXPORT query_column_base
{
- // Note that we keep shalow copies of the table, column, and conversion
+ // Note that we keep shallow copies of the table, column, and conversion
// expression. The latter can be NULL.
//
- query_column (const char* table,
- const char* column,
- const char* conv,
- unsigned short prec = 0xFFF,
- short scale = 0xFFF)
- : table_ (table), column_ (column), conversion_ (conv),
- prec_ (prec), scale_ (scale)
+ query_column_base (const char* table,
+ const char* column,
+ const char* conv,
+ unsigned short prec,
+ short scale)
+ : table_ (table), column_ (column), conversion_ (conv),
+ prec_ (prec), scale_ (scale)
{
}
@@ -467,6 +472,51 @@ namespace odb
return scale_;
}
+ protected:
+ const char* table_;
+ const char* column_;
+ const char* conversion_;
+
+ unsigned short prec_;
+ short scale_;
+ };
+
+ template <typename T, typename T2>
+ class copy_bind: public val_bind<T>
+ {
+ public:
+ explicit
+ copy_bind (const T2& v): val_bind<T> (val), val (v) {}
+
+ const T val;
+ };
+
+ template <typename T>
+ const T&
+ type_instance ();
+
+ template <typename T, database_type_id ID>
+ struct query_column: query_column_base
+ {
+ // Note that we keep shalow copies of the table, column, and conversion
+ // expression. The latter can be NULL.
+ //
+ query_column (const char* table,
+ const char* column,
+ const char* conv,
+ unsigned short prec = 0xFFF,
+ short scale = 0xFFF)
+ : query_column_base (table, column, conv, prec, scale) {}
+
+ // Implementation is in query-dynamic.ixx.
+ //
+ query_column (odb::query_column<T>&,
+ const char* table,
+ const char* column,
+ const char* conv,
+ unsigned short prec = 0xFFF,
+ short scale = 0xFFF);
+
// is_null, is_not_null
//
public:
@@ -1137,14 +1187,6 @@ namespace odb
q.append (c.table (), c.column ());
return q;
}
-
- private:
- const char* table_;
- const char* column_;
- const char* conversion_;
-
- unsigned short prec_;
- short scale_;
};
//
@@ -1153,27 +1195,15 @@ namespace odb
// predicates for these types.
//
- struct LIBODB_ORACLE_EXPORT lob_query_column
+ struct LIBODB_ORACLE_EXPORT lob_query_column: query_column_base
{
// Note that we keep shallow copies of the table and column names.
// There is also no need for conversion expression since the only
// valid tests are is IS NULL/IS NOT NULL.
//
lob_query_column (const char* table, const char* column)
- : table_ (table), column_ (column)
- {
- }
-
- const char*
- table () const
+ : query_column_base (table, column, 0, 0xFFF, 0xFFF)
{
- return table_;
- }
-
- const char*
- column () const
- {
- return column_;
}
// is_null, is_not_null
@@ -1194,10 +1224,6 @@ namespace odb
q += "IS NOT NULL";
return q;
}
-
- private:
- const char* table_;
- const char* column_;
};
template <typename T>
@@ -1207,6 +1233,11 @@ namespace odb
: lob_query_column (table, column)
{
}
+
+ // Implementation is in query-dynamic.ixx.
+ //
+ query_column (odb::query_column<T>&,
+ const char* table, const char* column, const char*);
};
template <typename T>
@@ -1216,6 +1247,11 @@ namespace odb
: lob_query_column (table, column)
{
}
+
+ // Implementation is in query-dynamic.ixx.
+ //
+ query_column (odb::query_column<T>&,
+ const char* table, const char* column, const char*);
};
template <typename T>
@@ -1225,6 +1261,11 @@ namespace odb
: lob_query_column (table, column)
{
}
+
+ // Implementation is in query-dynamic.ixx.
+ //
+ query_column (odb::query_column<T>&,
+ const char* table, const char* column, const char*);
};
// Provide operator+() for using columns to construct native
@@ -1890,6 +1931,11 @@ namespace odb
: query_base (qc)
{
}
+
+ query (const odb::query_base& q)
+ : query_base (q)
+ {
+ }
};
}
diff --git a/odb/oracle/query.ixx b/odb/oracle/query.ixx
index 611128c..224606f 100644
--- a/odb/oracle/query.ixx
+++ b/odb/oracle/query.ixx
@@ -16,7 +16,7 @@ namespace odb
inline void query_base::
append (val_bind<T> v, const char* conv)
{
- add (
+ append (
details::shared_ptr<query_param> (
new (details::shared) query_param_impl<T, ID> (v)),
conv);
@@ -26,7 +26,7 @@ namespace odb
inline void query_base::
append (ref_bind<T> r, const char* conv)
{
- add (
+ append (
details::shared_ptr<query_param> (
new (details::shared) query_param_impl<T, ID> (r)),
conv);
diff --git a/odb/oracle/traits.hxx b/odb/oracle/traits.hxx
index 0f7c635..2cbce04 100644
--- a/odb/oracle/traits.hxx
+++ b/odb/oracle/traits.hxx
@@ -556,7 +556,6 @@ namespace odb
{
public:
typedef const char* value_type;
- typedef const char* query_type;
typedef char* image_type;
static void
@@ -581,34 +580,40 @@ namespace odb
struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_string>:
c_string_value_traits
{
+ typedef const char* query_type;
};
template <>
struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_nstring>:
c_string_value_traits
{
+ typedef const char* query_type;
};
template <std::size_t N>
struct default_value_traits<char[N], id_string>: c_string_value_traits
{
+ typedef char query_type[N];
};
template <std::size_t N>
struct default_value_traits<const char[N], id_string>:
c_string_value_traits
{
+ typedef const char query_type[N];
};
template <std::size_t N>
struct default_value_traits<char[N], id_nstring>: c_string_value_traits
{
+ typedef char query_type[N];
};
template <std::size_t N>
struct default_value_traits<const char[N], id_nstring>:
c_string_value_traits
{
+ typedef const char query_type[N];
};
// std::vector<char> (buffer) specialization for RAW.
@@ -698,7 +703,7 @@ namespace odb
struct default_value_traits<char[N], id_raw>
{
typedef char* value_type;
- typedef const char* query_type;
+ typedef char query_type[N];
typedef char* image_type;
static void
@@ -729,7 +734,7 @@ namespace odb
struct default_value_traits<unsigned char[N], id_raw>
{
typedef unsigned char* value_type;
- typedef const unsigned char* query_type;
+ typedef unsigned char query_type[N];
typedef char* image_type;
static void
@@ -897,7 +902,6 @@ namespace odb
{
public:
typedef const char* value_type;
- typedef const char* query_type;
typedef lob_callback image_type;
static void
@@ -925,36 +929,42 @@ namespace odb
struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_clob>:
c_string_lob_value_traits
{
+ typedef const char* query_type;
};
template <>
struct LIBODB_ORACLE_EXPORT default_value_traits<const char*, id_nclob>:
c_string_lob_value_traits
{
+ typedef const char* query_type;
};
template <std::size_t N>
struct default_value_traits<char[N], id_clob>:
c_string_lob_value_traits
{
+ typedef char query_type[N];
};
template <std::size_t N>
struct default_value_traits<const char[N], id_clob>:
c_string_lob_value_traits
{
+ typedef const char query_type[N];
};
template <std::size_t N>
struct default_value_traits<char[N], id_nclob>:
c_string_lob_value_traits
{
+ typedef char query_type[N];
};
template <std::size_t N>
struct default_value_traits<const char[N], id_nclob>:
c_string_lob_value_traits
{
+ typedef const char query_type[N];
};
// std::vector<char> (buffer) specialization for BLOBs.
@@ -1072,7 +1082,7 @@ namespace odb
{
public:
typedef char* value_type;
- typedef const char* query_type;
+ typedef char query_type[N];
typedef lob_callback image_type;
static void
@@ -1125,7 +1135,7 @@ namespace odb
{
public:
typedef unsigned char* value_type;
- typedef const unsigned char* query_type;
+ typedef unsigned char query_type[N];
typedef lob_callback image_type;
static void