summaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
Diffstat (limited to 'odb/relational')
-rw-r--r--odb/relational/common-query.cxx167
-rw-r--r--odb/relational/common-query.hxx64
-rw-r--r--odb/relational/common.cxx571
-rw-r--r--odb/relational/common.hxx350
-rw-r--r--odb/relational/header.cxx62
-rw-r--r--odb/relational/header.hxx371
-rw-r--r--odb/relational/mssql/common.cxx16
-rw-r--r--odb/relational/mysql/common.cxx2
-rw-r--r--odb/relational/oracle/common.cxx18
-rw-r--r--odb/relational/pgsql/common.cxx2
-rw-r--r--odb/relational/source.cxx178
-rw-r--r--odb/relational/source.hxx17
-rw-r--r--odb/relational/sqlite/common.cxx2
13 files changed, 478 insertions, 1342 deletions
diff --git a/odb/relational/common-query.cxx b/odb/relational/common-query.cxx
new file mode 100644
index 0000000..e49132f
--- /dev/null
+++ b/odb/relational/common-query.cxx
@@ -0,0 +1,167 @@
+// file : odb/relational/common-query.cxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#include <odb/relational/common-query.hxx>
+
+using namespace std;
+
+namespace relational
+{
+ // query_alias_traits
+ //
+
+ void query_alias_traits::
+ generate_decl_body ()
+ {
+ os << "static const char table_name[];";
+ }
+
+ void query_alias_traits::
+ generate_def (semantics::data_member& m, semantics::class_& c)
+ {
+ // Come up with a table alias. Generally, we want it to be based
+ // on the column name. This is straightforward for single-column
+ // references. In case of a composite id, we will need to use the
+ // column prefix which is based on the data member name, unless
+ // overridden by the user. In the latter case the prefix can be
+ // empty, in which case we will just fall back on the member's
+ // public name.
+ //
+ string alias;
+ {
+ string n;
+
+ if (composite_wrapper (utype (*id_member (c))))
+ {
+ n = column_prefix (m, key_prefix_, default_name_);
+
+ if (n.empty ())
+ n = public_name_db (m);
+ else
+ n.resize (n.size () - 1); // Remove trailing underscore.
+ }
+ else
+ n = column_name (m, key_prefix_, default_name_);
+
+ alias = compose_name (column_prefix_, n);
+ }
+
+ generate_def (public_name (m), c, alias);
+ }
+
+ void query_alias_traits::
+ generate_def (string const& tag, semantics::class_& c, string const& alias)
+ {
+ semantics::class_* poly_root (polymorphic (c));
+ bool poly_derived (poly_root != 0 && poly_root != &c);
+ semantics::class_* poly_base (poly_derived ? &polymorphic_base (c) : 0);
+
+ if (poly_derived)
+ generate_def (tag, *poly_base, alias);
+
+ os << "const char alias_traits<"
+ << " " << class_fq_name (c) << "," << endl
+ << " id_" << db << "," << endl
+ << " " << scope_ << "::" << tag << "_tag>::" << endl
+ << "table_name[] = ";
+
+ if (poly_root != 0)
+ os << strlit (quote_id (alias + "_" + table_name (c).uname ()));
+ else
+ os << strlit (quote_id (alias));
+
+ os << ";"
+ << endl;
+ }
+
+ entry<query_alias_traits> query_alias_traits_;
+
+
+ // query_columns_base
+ //
+
+ entry<query_columns_base> query_columns_base_;
+
+ // query_columns
+ //
+
+ void query_columns::
+ column_ctor (string const& type, string const& name, string const& base)
+ {
+ os << name << " (";
+
+ if (multi_dynamic)
+ os << "odb::query_column< " << type << " >& qc," << endl;
+
+ os << "const char* t, const char* c, const char* conv)" << endl
+ << " : " << base << " (" << (multi_dynamic ? "qc, " : "") <<
+ "t, c, conv)"
+ << "{"
+ << "}";
+ }
+
+ void query_columns::
+ column_ctor_args_extra (semantics::data_member&)
+ {
+ }
+
+ void query_columns::
+ column_common (semantics::data_member& m,
+ string const& type,
+ string const& column,
+ string const& suffix)
+ {
+ string name (public_name (m));
+
+ if (decl_)
+ {
+ string type_id (database_type_id (m));
+
+ os << "// " << name << endl
+ << "//" << endl;
+
+ os << "typedef" << endl
+ << db << "::query_column<" << endl
+ << " " << db << "::value_traits<" << endl
+ << " " << type << "," << endl
+ << " " << type_id << " >::query_type," << endl
+ << " " << type_id << " >" << endl
+ << name << suffix << ";"
+ << endl;
+ }
+ else
+ {
+ // Note that here we don't use suffix.
+ //
+ string tmpl (ptr_ ? "pointer_query_columns" : "query_columns");
+ tmpl += "< " + fq_name_ + ", id_" + db.string () + ", A >" + scope_;
+
+ os << "template <typename A>" << endl
+ << "const typename " << tmpl << "::" << name << "_type_" << endl
+ << tmpl << "::" << endl
+ << name << " (";
+
+ // Pass common query column for registration.
+ //
+ if (multi_dynamic)
+ {
+ string tmpl (ptr_ ? "pointer_query_columns" : "query_columns");
+ tmpl += "< " + fq_name_ + ", id_common, typename A::common_traits >" +
+ scope_;
+
+ os << tmpl << "::" << name << "," << endl;
+ }
+
+ os << "A::" << "table_name, " << strlit (quote_id (column));
+
+ string const& conv (convert_to_expr (column_type (), m));
+ os << ", " << (conv.empty () ? "0" : strlit (conv));
+
+ column_ctor_args_extra (m);
+
+ os << ");"
+ << endl;
+ }
+ }
+}
diff --git a/odb/relational/common-query.hxx b/odb/relational/common-query.hxx
new file mode 100644
index 0000000..2e8fdd4
--- /dev/null
+++ b/odb/relational/common-query.hxx
@@ -0,0 +1,64 @@
+// file : odb/relational/common-query.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v3; see accompanying LICENSE file
+
+#ifndef ODB_RELATIONAL_COMMON_QUERY_HXX
+#define ODB_RELATIONAL_COMMON_QUERY_HXX
+
+#include <odb/relational/common.hxx>
+
+namespace relational
+{
+ //
+ //
+ struct query_alias_traits: ::query_alias_traits, virtual context
+ {
+ typedef query_alias_traits base_impl;
+
+ query_alias_traits (base const& x): base (x) {}
+
+ virtual void
+ generate_decl_body ();
+
+ virtual void
+ generate_def (semantics::data_member&, semantics::class_&);
+
+ virtual void
+ generate_def (string const& tag, semantics::class_&, string const& alias);
+ };
+
+ //
+ //
+ struct query_columns_base: ::query_columns_base, virtual context
+ {
+ typedef query_columns_base base_impl;
+
+ query_columns_base (base const& x): base (x) {const_ = "const ";}
+ };
+
+ //
+ //
+ struct query_columns: ::query_columns, virtual context
+ {
+ typedef query_columns base_impl;
+
+ query_columns (base const& x): base (x) {const_ = "const ";}
+
+ virtual string
+ database_type_id (semantics::data_member&) = 0;
+
+ virtual void
+ column_ctor (string const& type, string const& name, string const& base);
+
+ virtual void
+ column_ctor_args_extra (semantics::data_member&);
+
+ virtual void
+ column_common (semantics::data_member&,
+ string const& type,
+ string const& column,
+ string const& suffix);
+ };
+}
+
+#endif // ODB_RELATIONAL_COMMON_QUERY_HXX
diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx
index b8d2c60..2b0e87f 100644
--- a/odb/relational/common.cxx
+++ b/odb/relational/common.cxx
@@ -2,580 +2,17 @@
// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
// license : GNU GPL v3; see accompanying LICENSE file
-#include <string>
-#include <cstddef> // std::size_
-#include <cstdlib> // abort
-#include <sstream>
-#include <cxxabi.h> // abi::__cxa_demangle
-
#include <odb/relational/common.hxx>
using namespace std;
namespace relational
{
- // query_alias_traits
+ // member_database_type_id
//
-
- query_alias_traits::
- query_alias_traits (semantics::class_& c, bool decl)
- : decl_ (decl)
- {
- scope_ = "access::";
- scope_ += (object (c) ? "object_traits_impl" : "view_traits_impl");
- scope_ += "< " + class_fq_name (c) + ", id_" + db.string () + " >";
- }
-
- void query_alias_traits::
- traverse_object (semantics::class_& c)
- {
- // We don't want to traverse bases.
- //
- names (c);
- }
-
- void query_alias_traits::
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- // Base type.
- //
- if (m == 0)
- {
- object_columns_base::traverse_composite (m, c);
- return;
- }
-
- string old_scope (scope_);
- scope_ += "::" + public_name (*m) + "_tag";
-
- object_columns_base::traverse_composite (m, c);
-
- scope_ = old_scope;
- }
-
- void query_alias_traits::
- traverse_pointer (semantics::data_member& m, semantics::class_& c)
+ string member_database_type_id::
+ database_type_id (semantics::data_member&)
{
- // Ignore polymorphic id references.
- //
- if (m.count ("polymorphic-ref"))
- return;
-
- if (decl_)
- generate_decl (public_name (m), c);
- else
- {
- // Come up with a table alias. Generally, we want it to be based
- // on the column name. This is straightforward for single-column
- // references. In case of a composite id, we will need to use the
- // column prefix which is based on the data member name, unless
- // overridden by the user. In the latter case the prefix can be
- // empty, in which case we will just fall back on the member's
- // public name.
- //
- string alias;
- {
- string n;
-
- if (composite_wrapper (utype (*id_member (c))))
- {
- n = column_prefix (m, key_prefix_, default_name_);
-
- if (n.empty ())
- n = public_name_db (m);
- else
- n.resize (n.size () - 1); // Remove trailing underscore.
- }
- else
- n = column_name (m, key_prefix_, default_name_);
-
- alias = compose_name (column_prefix_, n);
- }
-
- generate_def (public_name (m), c, alias);
- }
- }
-
- void query_alias_traits::
- generate_decl (string const& tag, semantics::class_& c)
- {
- semantics::class_* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
- semantics::class_* poly_base (poly_derived ? &polymorphic_base (c) : 0);
-
- if (poly_derived)
- generate_decl (tag, *poly_base);
-
- os << "template <>" << endl
- << "struct alias_traits<" << endl
- << " " << class_fq_name (c) << "," << endl
- << " id_" << db << "," << endl
- << " " << scope_ << "::" << tag << "_tag>"
- << "{"
- << "static const char table_name[];";
-
- if (poly_derived)
- os << endl
- << "typedef alias_traits<" << endl
- << " " << class_fq_name (*poly_base) << "," << endl
- << " id_" << db << "," << endl
- << " " << scope_ << "::" << tag << "_tag>" << endl
- << "base_traits;";
-
- os << "};";
- }
-
- void query_alias_traits::
- generate_def (string const& tag, semantics::class_& c, string const& alias)
- {
- semantics::class_* poly_root (polymorphic (c));
- bool poly_derived (poly_root != 0 && poly_root != &c);
- semantics::class_* poly_base (poly_derived ? &polymorphic_base (c) : 0);
-
- if (poly_derived)
- generate_def (tag, *poly_base, alias);
-
- os << "const char alias_traits<"
- << " " << class_fq_name (c) << "," << endl
- << " id_" << db << "," << endl
- << " " << scope_ << "::" << tag << "_tag>::" << endl
- << "table_name[] = ";
-
- if (poly_root != 0)
- os << strlit (quote_id (alias + "_" + table_name (c).uname ()));
- else
- os << strlit (quote_id (alias));
-
- os << ";"
- << endl;
- }
-
- // query_columns_base
- //
-
- query_columns_base::
- query_columns_base (semantics::class_& c, bool decl)
- : decl_ (decl)
- {
- string const& n (class_fq_name (c));
-
- if (!decl)
- scope_ = "query_columns_base< " + n + ", id_" + db.string () + " >";
-
- tag_scope_ = "access::object_traits_impl< " + n + ", id_" +
- db.string () + " >";
- }
-
- void query_columns_base::
- traverse_object (semantics::class_& c)
- {
- // We don't want to traverse bases.
- //
- names (c);
- }
-
- void query_columns_base::
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- // Base type.
- //
- if (m == 0)
- {
- object_columns_base::traverse_composite (m, c);
- return;
- }
-
- // Don't generate an empty struct if we don't have any pointers.
- //
- if (!has_a (c, test_pointer))
- return;
-
- string name (public_name (*m));
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl
- << "struct " << name << "_base_"
- << "{";
-
- string old_tag_scope (tag_scope_);
- tag_scope_ += "::" + name + "_tag";
-
- object_columns_base::traverse_composite (m, c);
-
- tag_scope_ = old_tag_scope;
-
- os << "};";
- }
- else
- {
- string old_scope (scope_);
- string old_tag_scope (tag_scope_);
- scope_ += "::" + name + "_base_";
- tag_scope_ += "::" + name + "_tag";
-
- object_columns_base::traverse_composite (m, c);
-
- tag_scope_ = old_tag_scope;
- scope_ = old_scope;
- }
- }
-
- void query_columns_base::
- traverse_pointer (semantics::data_member& m, semantics::class_& c)
- {
- // Ignore polymorphic id references.
- //
- if (m.count ("polymorphic-ref"))
- return;
-
- string name (public_name (m));
- bool inv (inverse (m, key_prefix_));
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl;
-
- string const& fq_name (class_fq_name (c));
-
- os << "typedef" << endl
- << "odb::alias_traits<" << endl
- << " " << fq_name << "," << endl
- << " id_" << db << "," << endl
- << " " << tag_scope_ << "::" << name << "_tag>" << endl
- << name << "_alias_;"
- << endl;
-
- if (inv)
- {
- os << "typedef" << endl
- << "odb::query_pointer<" << endl
- << " odb::pointer_query_columns<" << endl
- << " " << fq_name << "," << endl
- << " id_" << db << "," << endl
- << " " << name << "_alias_ > >" << endl
- << name << "_type_ ;"
- << endl
- << "static const " << name << "_type_ " << name << ";"
- << endl;
- }
- }
- else
- {
- if (inv)
- os << "const " << scope_ << "::" << name << "_type_" << endl
- << scope_ << "::" << name << ";"
- << endl;
- }
- }
-
- // query_columns
- //
-
- query_columns::
- query_columns (bool ptr)
- : ptr_ (ptr), decl_ (true), in_ptr_ (false)
- {
- }
-
- query_columns::
- query_columns (bool ptr, semantics::class_& c) //@@ context::{cur,top}_object
- : ptr_ (ptr), decl_ (false), in_ptr_ (false)
- {
- scope_ = ptr ? "pointer_query_columns" : "query_columns";
- scope_ += "< " + class_fq_name (c) + ", id_" + db.string () + ", A >";
- }
-
- void query_columns::
- traverse_object (semantics::class_& c)
- {
- // We don't want to traverse bases.
- //
- names (c);
- }
-
- void query_columns::
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- // Base type.
- //
- if (m == 0)
- {
- object_columns_base::traverse_composite (m, c);
- return;
- }
-
- string name (public_name (*m));
- string suffix (in_ptr_ ? "_column_type_" : "_type_");
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl
- << "struct " << name << suffix;
-
- // Derive from the base in query_columns_base. It contains columns
- // data for the pointer members.
- //
- if (!ptr_ && has_a (c, test_pointer))
- os << ": " << name << "_base_";
-
- os << "{"
- << name << suffix << " (){}"; // Need user-defined default c-tor
- // for initialization of const.
-
- object_columns_base::traverse_composite (m, c);
-
- os << "};";
-
- if (!in_ptr_)
- os << "static const " << name << "_type_ " << name << ";"
- << endl;
- }
- else
- {
- // Handle nested members first.
- //
- string old_scope (scope_);
- scope_ += "::" + name + suffix;
-
- object_columns_base::traverse_composite (m, c);
-
- scope_ = old_scope;
-
- // Composite member. Note that here we don't use suffix.
- //
- os << "template <typename A>" << endl
- << "const typename " << scope_ << "::" << name << "_type_" << endl
- << scope_ << "::" << name << ";"
- << endl;
- }
- }
-
- void query_columns::
- column_ctor (string const& type, string const& base)
- {
- os << type << " (const char* t, const char* c, const char* conv)" << endl
- << " : " << base << " (t, c, conv)"
- << "{"
- << "}";
- }
-
- void query_columns::
- column_common (semantics::data_member& m,
- string const& type,
- string const& column,
- string const& suffix)
- {
- string name (public_name (m));
-
- if (decl_)
- {
- string type_id (database_type_id (m));
-
- os << "// " << name << endl
- << "//" << endl;
-
- os << "typedef" << endl
- << db << "::query_column<" << endl
- << " " << db << "::value_traits<" << endl
- << " " << type << "," << endl
- << " " << type_id << " >::query_type," << endl
- << " " << type_id << " >" << endl
- << name << suffix << ";"
- << endl;
- }
- else
- {
- // Note that here we don't use suffix.
- //
- os << "template <typename A>" << endl
- << "const typename " << scope_ << "::" << name << "_type_" << endl
- << scope_ << "::" << endl
- << name << " (A::" << "table_name, " << strlit (quote_id (column));
-
- string const& conv (convert_to_expr (column_type (), m));
- os << ", " << (conv.empty () ? "0" : strlit (conv));
-
- column_ctor_extra (m);
-
- os << ");"
- << endl;
- }
- }
-
- bool query_columns::
- traverse_column (semantics::data_member& m, string const& column, bool)
- {
- semantics::names* hint;
- semantics::type& t (utype (m, hint));
-
- column_common (m, t.fq_name (hint), column);
-
- if (decl_)
- {
- string name (public_name (m));
-
- os << "static const " << name << "_type_ " << name << ";"
- << endl;
- }
-
- return true;
- }
-
- void query_columns::
- traverse_pointer (semantics::data_member& m, semantics::class_& c)
- {
- // Ignore polymorphic id references.
- //
- if (m.count ("polymorphic-ref"))
- return;
-
- // If this is for the pointer_query_columns and the member is not
- // inverse, then create the normal member corresponding to the id
- // column. This will allow the user to check it for NULL or to
- // compare ids. In case this is for query_columns, then for the
- // inverse member everything has been generated in query_columns_base.
- //
- if (inverse (m, key_prefix_))
- return;
-
- string name (public_name (m));
-
- semantics::data_member& id (*id_member (c));
- semantics::names* hint;
- semantics::type& t (utype (id, hint));
-
- if (composite_wrapper (t))
- {
- // Composite id.
- //
-
- // For pointer_query_columns generate normal composite mapping.
- //
- if (ptr_)
- object_columns_base::traverse_pointer (m, c);
- else
- {
- // If this is a non-inverse relationship, then make the column have
- // a dual interface: that of an object pointer and of an id column.
- // The latter allows the user to, for example, use the is_null()
- // test in a natural way. For inverse relationships there is no
- // column and so the column interface is not available.
- //
- in_ptr_ = true;
- object_columns_base::traverse_pointer (m, c);
- in_ptr_ = false;
-
- if (decl_)
- {
- os << "typedef" << endl
- << "odb::query_pointer<" << endl
- << " odb::pointer_query_columns<" << endl
- << " " << class_fq_name (c) << "," << endl
- << " id_" << db << "," << endl
- << " " << name << "_alias_ > >" << endl
- << name << "_pointer_type_;"
- << endl;
-
- os << "struct " << name << "_type_: " <<
- name << "_pointer_type_, " << name << "_column_type_"
- << "{"
- << name << "_type_ (){}" // Need user-defined default c-tor
- // for initialization of const.
- << "};";
-
- os << "static const " << name << "_type_ " << name << ";"
- << endl;
- }
- }
- }
- else
- {
- // Simple id.
- //
- string type (t.fq_name (hint));
- string column (
- compose_name (
- column_prefix_, column_name (m, key_prefix_, default_name_)));
-
- // For pointer_query_columns generate normal column mapping.
- //
- if (ptr_)
- column_common (m, type, column);
- else
- {
- // If this is a non-inverse relationship, then make the column have
- // a dual interface: that of an object pointer and of an id column.
- // The latter allows the user to, for example, use the is_null()
- // test in a natural way. For inverse relationships there is no
- // column and so the column interface is not available.
- //
- column_common (m, type, column, "_column_type_");
-
- if (decl_)
- {
- os << "typedef" << endl
- << "odb::query_pointer<" << endl
- << " odb::pointer_query_columns<" << endl
- << " " << class_fq_name (c) << "," << endl
- << " id_" << db << "," << endl
- << " " << name << "_alias_ > >" << endl
- << name << "_pointer_type_;"
- << endl;
-
- os << "struct " << name << "_type_: " <<
- name << "_pointer_type_, " << name << "_column_type_"
- << "{"
- << name << "_type_ (){}"; // Need user-defined default c-tor
- // for initialization of const.
-
- column_ctor (name + "_type_", name + "_column_type_");
-
- os << "};";
- }
- }
-
- if (decl_)
- os << "static const " << name << "_type_ " << name << ";"
- << endl;
- }
- }
-
- //
- // Dynamic traversal support.
- //
-
- struct demangled_name
- {
- demangled_name (): s (0), n (0) {}
- ~demangled_name () {free (s);}
- char* s;
- size_t n;
- };
-
- static demangled_name name_;
-
- database entry_base::
- db (type_info const& ti)
- {
- char*& s (name_.s);
-
- int r;
- s = abi::__cxa_demangle (ti.name (), s, &name_.n, &r);
-
- if (r != 0)
- abort (); // We are in static initialization, so this is fatal.
-
- string str (s + 12); // 12 for "relational::"
- istringstream is (string (str, 0, str.find (':')));
-
- database d;
- if (!(is >> d))
- abort ();
-
- return d;
+ assert (false);
}
}
diff --git a/odb/relational/common.hxx b/odb/relational/common.hxx
index 1e7143f..a077d6f 100644
--- a/odb/relational/common.hxx
+++ b/odb/relational/common.hxx
@@ -5,11 +5,8 @@
#ifndef ODB_RELATIONAL_COMMON_HXX
#define ODB_RELATIONAL_COMMON_HXX
-#include <map>
#include <set>
-#include <cstddef> // std::size_t
#include <cassert>
-#include <typeinfo>
#include <odb/common.hxx>
#include <odb/relational/context.hxx>
@@ -215,350 +212,17 @@ namespace relational
{
}
+ // Has to be overriden.
+ //
virtual string
- database_type_id (semantics::data_member&)
- {
- assert (false);
- }
- };
-
- // Generate alias_traits specializations for pointers in this objects.
- //
- struct query_alias_traits: object_columns_base, virtual context
- {
- typedef query_alias_traits base;
-
- query_alias_traits (semantics::class_&, bool decl);
-
- virtual void
- traverse_object (semantics::class_&);
-
- virtual void
- traverse_composite (semantics::data_member*, semantics::class_&);
-
- virtual void
- traverse_pointer (semantics::data_member&, semantics::class_&);
-
- virtual void
- generate_decl (string const& tag, semantics::class_&);
-
- virtual void
- generate_def (string const& tag, semantics::class_&, string const& alias);
-
- protected:
- bool decl_;
- string scope_;
- };
-
- //
- //
- struct query_columns_base: object_columns_base, virtual context
- {
- typedef query_columns_base base;
-
- query_columns_base (semantics::class_&, bool decl);
-
- virtual void
- traverse_object (semantics::class_&);
-
- virtual void
- traverse_composite (semantics::data_member*, semantics::class_&);
-
- virtual void
- traverse_pointer (semantics::data_member&, semantics::class_&);
-
- protected:
- bool decl_;
- string scope_;
- string tag_scope_;
- };
-
- //
- //
- struct query_columns: object_columns_base, virtual context
- {
- typedef query_columns base;
-
- query_columns (bool ptr);
- query_columns (bool ptr, semantics::class_&);
-
- virtual string
- database_type_id (semantics::data_member&)
- {
- assert (false);
- }
-
- virtual void
- column_ctor (string const& type, string const& base);
-
- virtual void
- column_ctor_extra (semantics::data_member&)
- {
- }
-
- virtual void
- traverse_object (semantics::class_&);
-
- virtual void
- traverse_composite (semantics::data_member*, semantics::class_&);
-
- virtual void
- column_common (semantics::data_member&,
- string const& type,
- string const& column,
- string const& suffix = "_type_");
-
- virtual bool
- traverse_column (semantics::data_member&, string const&, bool);
-
- virtual void
- traverse_pointer (semantics::data_member&, semantics::class_&);
-
- protected:
- bool ptr_;
- bool decl_;
-
- bool in_ptr_; // True if we are "inside" an object pointer.
-
- string scope_;
- string table_;
- string default_table_;
- };
-
- //
- // Dynamic traversal support.
- //
-
- template <typename B>
- struct factory
- {
- static B*
- create (B const& prototype)
- {
- database db (context::current ().options.database ()[0]);
-
- if (map_ != 0)
- {
- typename map::const_iterator i (map_->find (db));
-
- if (i != map_->end ())
- return i->second (prototype);
- }
-
- return new B (prototype);
- }
-
- private:
- template <typename>
- friend struct entry;
-
- static void
- init ()
- {
- if (factory<B>::count_++ == 0)
- factory<B>::map_ = new typename factory<B>::map;
- }
-
- static void
- term ()
- {
- if (--factory<B>::count_ == 0)
- delete factory<B>::map_;
- }
-
- typedef B* (*create_func) (B const&);
- typedef std::map<database, create_func> map;
- static map* map_;
- static std::size_t count_;
+ database_type_id (semantics::data_member&);
};
-
- template <typename B>
- typename factory<B>::map* factory<B>::map_;
-
- template <typename B>
- std::size_t factory<B>::count_;
-
- struct entry_base
- {
- static database
- db (std::type_info const&);
- };
-
- template <typename D>
- struct entry: entry_base
- {
- typedef typename D::base base;
-
- entry ()
- {
- factory<base>::init ();
- (*factory<base>::map_)[db (typeid (D))] = &create;
- }
-
- ~entry ()
- {
- factory<base>::term ();
- }
-
- static base*
- create (base const& prototype)
- {
- return new D (prototype);
- }
- };
-
- template <typename B>
- struct instance
- {
- typedef relational::factory<B> factory;
-
- ~instance ()
- {
- delete x_;
- }
-
- instance ()
- {
- B prototype;
- x_ = factory::create (prototype);
- }
-
- template <typename A1>
- instance (A1& a1)
- {
- B prototype (a1);
- x_ = factory::create (prototype);
- }
-
- template <typename A1>
- instance (A1 const& a1)
- {
- B prototype (a1);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2>
- instance (A1& a1, A2& a2)
- {
- B prototype (a1, a2);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2>
- instance (A1 const& a1, A2 const& a2)
- {
- B prototype (a1, a2);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2, typename A3>
- instance (A1& a1, A2& a2, A3& a3)
- {
- B prototype (a1, a2, a3);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2, typename A3>
- instance (A1 const& a1, A2 const& a2, A3 const& a3)
- {
- B prototype (a1, a2, a3);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2, typename A3, typename A4>
- instance (A1& a1, A2& a2, A3& a3, A4& a4)
- {
- B prototype (a1, a2, a3, a4);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2, typename A3, typename A4>
- instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4)
- {
- B prototype (a1, a2, a3, a4);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2, typename A3, typename A4, typename A5>
- instance (A1& a1, A2& a2, A3& a3, A4& a4, A5& a5)
- {
- B prototype (a1, a2, a3, a4, a5);
- x_ = factory::create (prototype);
- }
-
- template <typename A1, typename A2, typename A3, typename A4, typename A5>
- instance (A1 const& a1, A2 const& a2, A3 const& a3, A4 const& a4,
- A5 const& a5)
- {
- B prototype (a1, a2, a3, a4, a5);
- x_ = factory::create (prototype);
- }
-
- instance (instance const& i)
- {
- // This is tricky: use the other instance as a prototype.
- //
- x_ = factory::create (*i.x_);
- }
-
- B*
- operator-> () const
- {
- return x_;
- }
-
- B&
- operator* () const
- {
- return *x_;
- }
-
- B*
- get () const
- {
- return x_;
- }
-
- private:
- instance& operator= (instance const&);
-
- private:
- B* x_;
- };
-
- template <typename T>
- inline traversal::edge_base&
- operator>> (instance<T>& n, traversal::edge_base& e)
- {
- n->edge_traverser (e);
- return e;
- }
-
- template <typename T>
- inline traversal::relational::edge_base&
- operator>> (instance<T>& n, traversal::relational::edge_base& e)
- {
- n->edge_traverser (e);
- return e;
- }
-
- template <typename T>
- inline traversal::node_base&
- operator>> (traversal::edge_base& e, instance<T>& n)
- {
- e.node_traverser (*n);
- return *n;
- }
-
- template <typename T>
- inline traversal::relational::node_base&
- operator>> (traversal::relational::edge_base& e, instance<T>& n)
- {
- e.node_traverser (*n);
- return *n;
- }
}
#include <odb/relational/common.txx>
+// Other common parts.
+//
+#include <odb/relational/common-query.hxx>
+
#endif // ODB_RELATIONAL_COMMON_HXX
diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx
index 099dc33..543e1ac 100644
--- a/odb/relational/header.cxx
+++ b/odb/relational/header.cxx
@@ -60,6 +60,16 @@ traverse_object (type& c)
object_public_extra_pre (c);
+ // For dynamic multi-database support also generate common traits
+ // alias (used in query aliasing).
+ //
+ if (options.generate_query () && multi_dynamic)
+ {
+ os << "typedef access::object_traits_impl< " << type << ", " <<
+ "id_common > common_traits;"
+ << endl;
+ }
+
// Polymorphic root_traits, base_traits, and discriminator_image_type.
//
if (poly)
@@ -155,8 +165,7 @@ traverse_object (type& c)
// Generate object pointer tags here unless we are generating dynamic
// multi-database support, in which case they generated in object_traits.
//
- if (options.multi_database () != multi_database::dynamic &&
- has_a (c, test_pointer | exclude_base))
+ if (!multi_dynamic && has_a (c, test_pointer | exclude_base))
{
query_tags t; // Not customizable.
t.traverse (c);
@@ -501,18 +510,34 @@ traverse_object (type& c)
os << "static result<object_type>" << endl
<< "query (database&, const query_base_type&);"
<< endl;
+
+ if (multi_dynamic)
+ os << "static result<object_type>" << endl
+ << "query (database&, const odb::query_base&);"
+ << endl;
}
os << "static unsigned long long" << endl
<< "erase_query (database&, const query_base_type&);"
<< endl;
+ if (multi_dynamic)
+ os << "static unsigned long long" << endl
+ << "erase_query (database&, const odb::query_base&);"
+ << endl;
+
if (options.generate_prepared ())
{
os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
<< "prepare_query (connection&, const char*, const query_base_type&);"
<< endl;
+ if (multi_dynamic)
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, " <<
+ "const odb::query_base&);"
+ << endl;
+
os << "static odb::details::shared_ptr<result_impl>" << endl
<< "execute_query (prepared_query_impl&);"
<< endl;
@@ -626,7 +651,7 @@ traverse_object (type& c)
os << "};";
- // object_traits_impl< , id_default>
+ // object_traits_impl< , id_common>
//
// Note that it is not generated for reuse-abstract classes.
//
@@ -635,7 +660,7 @@ traverse_object (type& c)
{
os << "template <>" << endl
<< "class access::object_traits_impl< " << type << ", " <<
- "id_default >:" << endl
+ "id_common >:" << endl
<< " public access::object_traits_impl< " << type << ", " <<
"id_" << db << " >"
<< "{"
@@ -663,6 +688,16 @@ traverse_view (type& c)
view_public_extra_pre (c);
+ // For dynamic multi-database support also generate common traits
+ // alias (used in query aliasing).
+ //
+ if (multi_dynamic)
+ {
+ os << "typedef access::view_traits_impl< " << type << ", " <<
+ "id_common > common_traits;"
+ << endl;
+ }
+
// image_type
//
image_type_->traverse (c);
@@ -677,7 +712,7 @@ traverse_view (type& c)
// Generate associated object tags here unless we are generating dynamic
// multi-database support, in which case they generated in object_traits.
//
- if (options.multi_database () != multi_database::dynamic)
+ if (!multi_dynamic)
{
query_tags t; // Not customizable.
t.traverse (c);
@@ -744,16 +779,29 @@ traverse_view (type& c)
// query ()
//
if (!options.omit_unprepared ())
+ {
os << "static result<view_type>" << endl
<< "query (database&, const query_base_type&);"
<< endl;
+ if (multi_dynamic)
+ os << "static result<view_type>" << endl
+ << "query (database&, const odb::query_base&);"
+ << endl;
+ }
+
if (options.generate_prepared ())
{
os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
<< "prepare_query (connection&, const char*, const query_base_type&);"
<< endl;
+ if (multi_dynamic)
+ os << "static odb::details::shared_ptr<prepared_query_impl>" << endl
+ << "prepare_query (connection&, const char*, " <<
+ "const odb::query_base&);"
+ << endl;
+
os << "static odb::details::shared_ptr<result_impl>" << endl
<< "execute_query (prepared_query_impl&);"
<< endl;
@@ -763,14 +811,14 @@ traverse_view (type& c)
os << "};";
- // view_traits_impl< , id_default>
+ // view_traits_impl< , id_common>
//
if (options.default_database_specified () &&
options.default_database () == db)
{
os << "template <>" << endl
<< "class access::view_traits_impl< " << type << ", " <<
- "id_default >:" << endl
+ "id_common >:" << endl
<< " public access::view_traits_impl< " << type << ", " <<
"id_" << db << " >"
<< "{"
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index 1ca87c6..89ef664 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -141,216 +141,6 @@ namespace relational
traversal::names names_member_;
};
- //
- // query_columns_type
- //
-
- struct query_columns_bases: traversal::class_, virtual context
- {
- typedef query_columns_bases base;
-
- query_columns_bases (bool ptr, bool first = true)
- : ptr_ (ptr), first_ (first)
- {
- }
-
- virtual void
- traverse (type& c)
- {
- // Ignore transient bases. Not used for views.
- //
- if (!object (c))
- return;
-
- if (first_)
- {
- os << ":" << endl
- << " ";
- first_ = false;
- }
- else
- {
- os << "," << endl
- << " ";
- }
-
- os << (ptr_ ? "pointer_query_columns" : "query_columns") << "< " <<
- class_fq_name (c) << ", id_" << db << ", ";
-
- // If our base is polymorphic, then it has its own table/alias.
- //
- if (polymorphic (c))
- os << "typename A::base_traits";
- else
- os << "A";
-
- os << " >";
- }
-
- private:
- bool ptr_;
- bool first_;
- };
-
- struct query_columns_base_aliases: traversal::class_, virtual context
- {
- typedef query_columns_base_aliases base;
-
- query_columns_base_aliases (bool ptr)
- : ptr_ (ptr)
- {
- }
-
- virtual void
- traverse (type& c)
- {
- // Ignore transient bases. Not used for views.
- //
- if (!object (c))
- return;
-
- string const& name (class_name (c));
-
- os << "// " << name << endl
- << "//" << endl
- << "typedef " <<
- (ptr_ ? "pointer_query_columns" : "query_columns") << "< " <<
- class_fq_name (c) << ", id_" << db << ", ";
-
- if (polymorphic (c))
- os << "typename A::base_traits";
- else
- os << "A";
-
- os << " > " << name << ";"
- << endl;
- }
-
- private:
- bool ptr_;
- };
-
- struct query_columns_type: traversal::class_, virtual context
- {
- typedef query_columns_type base;
-
- // Depending on the ptr argument, generate query_columns or
- // pointer_query_columns specialization. The latter is used
- // for object pointers where we don't support nested pointers.
- //
- query_columns_type (bool ptr): ptr_ (ptr) {}
-
- virtual void
- traverse (type& c)
- {
- string const& type (class_fq_name (c));
-
- if (ptr_)
- {
- os << "template <typename A>" << endl
- << "struct pointer_query_columns< " << type << ", id_" << db <<
- ", A >";
-
- // If we don't have pointers (in the whole hierarchy), then
- // pointer_query_columns and query_columns are the same.
- //
- if (!has_a (c, test_pointer | include_base))
- {
- os << ":" << endl
- << " query_columns< " << type << ", id_" << db << ", A >"
- << "{"
- << "};";
- }
- else
- {
- {
- instance<query_columns_bases> b (ptr_);
- traversal::inherits i (*b);
- inherits (c, i);
- }
-
- os << "{";
-
- {
- instance<query_columns_base_aliases> b (ptr_);
- traversal::inherits i (*b);
- inherits (c, i);
- }
-
- {
- instance<query_columns> t (ptr_);
- t->traverse (c);
- }
-
- os << "};";
-
- {
- instance<query_columns> t (ptr_, c);
- t->traverse (c);
- }
- }
- }
- else
- {
- bool has_ptr (has_a (c, test_pointer | exclude_base));
-
- if (has_ptr)
- {
- // This class contains everything for inverse pointers and
- // aliases for non-inverse ones. It doesn't depend on the
- // table alias (A) template argument.
- //
- os << "template <>" << endl
- << "struct query_columns_base< " << type << ", id_" <<
- db << " >"
- << "{";
-
- bool true_ (true); //@@ (im)perfect forwarding.
- instance<query_columns_base> t (c, true_);
- t->traverse (c);
-
- os << "};";
- }
-
- os << "template <typename A>" << endl
- << "struct query_columns< " << type << ", id_" << db << ", A >";
-
- if (has_ptr)
- os << ":" << endl
- << " query_columns_base< " << type << ", id_" << db << " >";
-
- {
- instance<query_columns_bases> b (ptr_, !has_ptr);
- traversal::inherits i (*b);
- inherits (c, i);
- }
-
- os << "{";
-
- {
- instance<query_columns_base_aliases> b (ptr_);
- traversal::inherits i (*b);
- inherits (c, i);
- }
-
- {
- instance<query_columns> t (ptr_);
- t->traverse (c);
- }
-
- os << "};";
-
- {
- instance<query_columns> t (ptr_, c);
- t->traverse (c);
- }
- }
- }
-
- public:
- bool ptr_;
- };
-
// Member-specific traits types for container members.
//
struct container_traits: object_members_base, virtual context
@@ -957,8 +747,8 @@ namespace relational
: id_image_member_ ("id_"),
version_image_member_ ("version_"),
discriminator_image_member_ ("discriminator_"),
- query_columns_type_ (false),
- pointer_query_columns_type_ (true)
+ query_columns_type_ (false, true),
+ pointer_query_columns_type_ (true, true)
{
}
@@ -968,8 +758,8 @@ namespace relational
id_image_member_ ("id_"),
version_image_member_ ("version_"),
discriminator_image_member_ ("discriminator_"),
- query_columns_type_ (false),
- pointer_query_columns_type_ (true)
+ query_columns_type_ (false, true),
+ pointer_query_columns_type_ (true, true)
{
}
@@ -1032,12 +822,17 @@ namespace relational
{
typedef class2 base;
- class2 (): query_columns_type_ (false) {}
+ class2 ()
+ : query_columns_type_ (false, true),
+ view_query_columns_type_ (true)
+ {
+ }
class2 (class_ const&)
: root_context (), //@@ -Wextra
context (),
- query_columns_type_ (false)
+ query_columns_type_ (false, true),
+ view_query_columns_type_ (true)
{
}
@@ -1072,13 +867,7 @@ namespace relational
// in pass 1 (see the comment in class1 for details).
//
if (has_ptr)
- {
- bool true_ (true); //@@ (im)perfect forwarding
- instance<query_alias_traits> t (c, true_);
- t->traverse (c);
-
query_columns_type_->traverse (c);
- }
}
// Move header comment out of if-block if adding any code here.
@@ -1087,134 +876,14 @@ namespace relational
virtual void
traverse_view (type& c)
{
- string const& type (class_fq_name (c));
-
// query_columns
//
- size_t obj_count (c.get<size_t> ("object-count"));
-
- if (obj_count != 0)
+ if (c.get<size_t> ("object-count") != 0)
{
os << "// " << class_name (c) << endl
<< "//" << endl;
- view_objects& objs (c.get<view_objects> ("objects"));
-
- // Generate alias_traits specializations.
- //
- {
- bool true_ (true); //@@ (im)perfect forwarding
- instance<query_alias_traits> at (c, true_);
-
- for (view_objects::const_iterator i (objs.begin ());
- i < objs.end ();
- ++i)
- {
- if (i->kind != view_object::object)
- continue; // Skip tables.
-
- if (i->alias.empty ())
- continue;
-
- semantics::class_& o (*i->obj);
- qname const& t (table_name (o));
-
- // Check that the alias is not the same as the table name
- // (if this is a polymorphic object, then the alias is just
- // a prefix).
- //
- if (polymorphic (o) || t.qualified () || i->alias != t.uname ())
- at->generate_decl (i->alias, o);
- }
- }
-
- os << "struct access::view_traits_impl< " << type << ", id_" <<
- db << " >::query_columns";
-
- if (obj_count > 1)
- {
- os << "{";
-
- for (view_objects::const_iterator i (objs.begin ());
- i < objs.end ();
- ++i)
- {
- if (i->kind != view_object::object)
- continue; // Skip tables.
-
- bool alias (!i->alias.empty ());
- semantics::class_& o (*i->obj);
- string const& oname (alias ? i->alias : class_name (o));
- string const& otype (class_fq_name (o));
- qname const& table (table_name (o));
-
- os << "// " << oname << endl
- << "//" << endl
- << "typedef" << endl
- << "odb::pointer_query_columns<" << endl
- << " " << otype << "," << endl
- << " id_" << db << "," << endl;
-
- if (alias && (polymorphic (o) ||
- table.qualified () ||
- i->alias != table.uname ()))
- {
- os << " odb::alias_traits< " << otype << "," << endl
- << " id_" << db << "," << endl
- << " access::view_traits_impl< " << type << ", id_" <<
- db << " >::" << i->alias << "_tag> >" << endl;
- }
- else
- os << " odb::access::object_traits_impl< " << otype <<
- ", id_" << db << " > >" << endl;
-
- os << oname << ";"
- << endl;
- }
-
- os << "};";
- }
- else
- {
- // For a single object view we generate a shortcut without
- // an intermediate typedef.
- //
- view_object const* vo (0);
- for (view_objects::const_iterator i (objs.begin ());
- vo == 0 && i < objs.end ();
- ++i)
- {
- if (i->kind == view_object::object)
- vo = &*i;
- }
-
- bool alias (!vo->alias.empty ());
- semantics::class_& o (*vo->obj);
- string const& otype (class_fq_name (o));
- qname const& table (table_name (o));
-
- os << ":" << endl
- << " odb::pointer_query_columns<" << endl
- << " " << otype << "," << endl
- << " id_" << db << "," << endl;
-
- if (alias && (polymorphic (o) ||
- table.qualified () ||
- vo->alias != table.uname ()))
- {
- os << " odb::alias_traits<" << endl
- << " " << otype << "," << endl
- << " id_" << db << "," << endl
- << " access::view_traits_impl< " << type << ", id_" <<
- db << " >::" << vo->alias << "_tag> >";
- }
- else
- os << " odb::access::object_traits_impl< " << otype <<
- ", id_" << db << " > >";
-
- os << "{"
- << "};";
- }
+ view_query_columns_type_->traverse (c);
}
// Move header comment out of if-block if adding any code here.
@@ -1227,6 +896,7 @@ namespace relational
private:
instance<query_columns_type> query_columns_type_;
+ instance<view_query_columns_type> view_query_columns_type_;
};
struct include: virtual context
@@ -1236,12 +906,8 @@ namespace relational
virtual void
generate ()
{
- os << "#include <odb/details/buffer.hxx>" << endl;
-
- if (options.generate_query ())
- os << "#include <odb/details/shared-ptr.hxx>" << endl;
-
- os << endl;
+ os << "#include <odb/details/buffer.hxx>" << endl
+ << endl;
os << "#include <odb/" << db << "/version.hxx>" << endl
<< "#include <odb/" << db << "/forward.hxx>" << endl
@@ -1249,8 +915,13 @@ namespace relational
<< "#include <odb/" << db << "/" << db << "-types.hxx>" << endl;
if (options.generate_query ())
+ {
os << "#include <odb/" << db << "/query.hxx>" << endl;
+ if (multi_dynamic)
+ os << "#include <odb/" << db << "/query-dynamic.hxx>" << endl;
+ }
+
os << endl;
}
};
diff --git a/odb/relational/mssql/common.cxx b/odb/relational/mssql/common.cxx
index d802e54..a16063b 100644
--- a/odb/relational/mssql/common.cxx
+++ b/odb/relational/mssql/common.cxx
@@ -473,7 +473,7 @@ namespace relational
struct query_columns: relational::query_columns, context
{
- query_columns (base const& x): base (x) {}
+ query_columns (base const& x): base_impl (x) {}
virtual string
database_type_id (semantics::data_member& m)
@@ -482,20 +482,26 @@ namespace relational
}
virtual void
- column_ctor (string const& type, string const& base)
+ column_ctor (string const& type, string const& name, string const& base)
{
- os << type << " (const char* t," << endl
+ os << name << " (";
+
+ if (multi_dynamic)
+ os << "odb::query_column< " << type << " >& qc," << endl;
+
+ os << "const char* t," << endl
<< "const char* c," << endl
<< "const char* conv," << endl
<< "unsigned short p = 0," << endl
<< "unsigned short s = 0xFFFF)" << endl
- << " : " << base << " (t, c, conv, p, s)"
+ << " : " << base << " (" << (multi_dynamic ? "qc, " : "") <<
+ "t, c, conv, p, s)"
<< "{"
<< "}";
}
virtual void
- column_ctor_extra (semantics::data_member& m)
+ column_ctor_args_extra (semantics::data_member& m)
{
// For some types we need to pass precision and scale.
//
diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx
index 9d62b6b..bbf2971 100644
--- a/odb/relational/mysql/common.cxx
+++ b/odb/relational/mysql/common.cxx
@@ -373,7 +373,7 @@ namespace relational
struct query_columns: relational::query_columns, context
{
- query_columns (base const& x): base (x) {}
+ query_columns (base const& x): base_impl (x) {}
virtual string
database_type_id (semantics::data_member& m)
diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx
index 04bb0f8..b1f5398 100644
--- a/odb/relational/oracle/common.cxx
+++ b/odb/relational/oracle/common.cxx
@@ -405,23 +405,29 @@ namespace relational
struct query_columns: relational::query_columns, context
{
- query_columns (base const& x): base (x) {}
+ query_columns (base const& x): base_impl (x) {}
- virtual void
- column_ctor (string const& type, string const& base)
+ void
+ column_ctor (string const& type, string const& name, string const& base)
{
- os << type << " (const char* t," << endl
+ os << name << " (";
+
+ if (multi_dynamic)
+ os << "odb::query_column< " << type << " >& qc," << endl;
+
+ os << "const char* t," << endl
<< "const char* c," << endl
<< "const char* conv," << endl
<< "unsigned short p = 0xFFF," << endl
<< "short s = 0xFFF)" << endl
- << " : " << base << " (t, c, conv, p, s)"
+ << " : " << base << " (" << (multi_dynamic ? "qc, " : "") <<
+ "t, c, conv, p, s)"
<< "{"
<< "}";
}
virtual void
- column_ctor_extra (semantics::data_member& m)
+ column_ctor_args_extra (semantics::data_member& m)
{
// For some types we need to pass precision and scale.
//
diff --git a/odb/relational/pgsql/common.cxx b/odb/relational/pgsql/common.cxx
index 811269e..5d415c6 100644
--- a/odb/relational/pgsql/common.cxx
+++ b/odb/relational/pgsql/common.cxx
@@ -322,7 +322,7 @@ namespace relational
struct query_columns: relational::query_columns, context
{
- query_columns (base const& x): base (x) {}
+ query_columns (base const& x): base_impl (x) {}
virtual string
database_type_id (semantics::data_member& m)
diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx
index 21c0f57..74690d6 100644
--- a/odb/relational/source.cxx
+++ b/odb/relational/source.cxx
@@ -62,30 +62,10 @@ traverse_object (type& c)
// Query (abstract and concrete).
//
+ // query_columns
+ //
if (options.generate_query ())
- {
- bool has_ptr (has_a (c, test_pointer | exclude_base));
-
- // Generate alias_traits specializations. While the class
- // is generated even if our base has a pointer, there is
- // not source code if we don't have pointers ourselves.
- //
- if (has_ptr)
- {
- bool false_ (false); //@@ (im)perfect forwarding
- instance<query_alias_traits> t (c, false_);
- t->traverse (c);
- }
-
- // query_columns_base
- //
- if (has_ptr)
- {
- bool false_ (false); //@@ (im)perfect forwarding.
- instance<query_columns_base> t (c, false_);
- t->traverse (c);
- }
- }
+ query_columns_type_->traverse (c);
//
// Containers (abstract and concrete).
@@ -2649,6 +2629,16 @@ traverse_object (type& c)
<< endl
<< "return result<object_type> (r);"
<< "}";
+
+ // query(odb::query_base)
+ //
+ if (multi_dynamic)
+ os << "result< " << traits << "::object_type >" << endl
+ << traits << "::" << endl
+ << "query (database& db, const odb::query_base& q)"
+ << "{"
+ << "return query (db, query_base_type (q));"
+ << "}";
}
// erase_query
@@ -2669,11 +2659,22 @@ traverse_object (type& c)
<< "return st.execute ();"
<< "}";
+ // erase_query(odb::query_base)
+ //
+ if (multi_dynamic)
+ os << "unsigned long long " << traits << "::" << endl
+ << "erase_query (database& db, const odb::query_base& q)"
+ << "{"
+ << "return erase_query (db, query_base_type (q));"
+ << "}";
+
// Prepared. Very similar to unprepared but has some annoying variations
// that make it difficult to factor out something common.
//
if (options.generate_prepared ())
{
+ // prepare_query
+ //
os << "odb::details::shared_ptr<prepared_query_impl>" << endl
<< traits << "::" << endl
<< "prepare_query (connection& c, const char* n, " <<
@@ -2732,6 +2733,19 @@ traverse_object (type& c)
<< "return r;"
<< "}";
+ // prepare_query(odb::query_base)
+ //
+ if (multi_dynamic)
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const odb::query_base& q)"
+ << "{"
+ << "return prepare_query (c, n, query_base_type (q));"
+ << "}";
+
+ // execute_query
+ //
os << "odb::details::shared_ptr<result_impl>" << endl
<< traits << "::" << endl
<< "execute_query (prepared_query_impl& q)"
@@ -2807,10 +2821,10 @@ traverse_object (type& c)
// Generate function table registration for dynamic multi-database
// support.
//
- if (options.multi_database () == multi_database::dynamic)
+ if (multi_dynamic)
{
string fn (flat_name (type));
- string dt ("access::object_traits_impl< " + type + ", id_default >");
+ string dt ("access::object_traits_impl< " + type + ", id_common >");
os << "static const" << endl
<< dt << "::" << endl
@@ -2854,9 +2868,28 @@ traverse_object (type& c)
<< "&" << traits << "::erase";
}
+ if (options.generate_query ())
+ {
+ if (!options.omit_unprepared ())
+ os << "," << endl
+ << "&" << traits << "::query";
+
+ os << "," << endl
+ << "&" << traits << "::erase_query";
+
+ if (options.generate_prepared ())
+ {
+ os << "," << endl
+ << "&" << traits << "::prepare_query";
+
+ os << "," << endl
+ << "&" << traits << "::execute_query";
+ }
+ }
+
os << "};";
- os << "static const function_table_entry< " << type << ", " <<
+ os << "static const object_function_table_entry< " << type << ", " <<
"id_" << db << " >" << endl
<< "function_table_entry_" << fn << "_ (" << endl
<< "&function_table_" << fn << "_);"
@@ -2877,38 +2910,10 @@ traverse_view (type& c)
view_extra (c);
+ // query_columns
+ //
if (c.get<size_t> ("object-count") != 0)
- {
- view_objects& objs (c.get<view_objects> ("objects"));
-
- // Generate alias_traits specializations.
- //
- {
- bool false_ (false); //@@ (im)perfect forwarding
- instance<query_alias_traits> at (c, false_);
-
- for (view_objects::const_iterator i (objs.begin ());
- i < objs.end ();
- ++i)
- {
- if (i->kind != view_object::object)
- continue; // Skip tables.
-
- if (i->alias.empty ())
- continue;
-
- semantics::class_& o (*i->obj);
- qname const& t (table_name (o));
-
- // Check that the alias is not the same as the table name
- // (if this is a polymorphic object, then the alias is just
- // a prefix).
- //
- if (polymorphic (o) || t.qualified () || i->alias != t.uname ())
- at->generate_def (i->alias, o, i->alias);
- }
- }
- }
+ view_query_columns_type_->traverse (c);
//
// Functions.
@@ -3684,6 +3689,16 @@ traverse_view (type& c)
<< endl
<< "return result<view_type> (r);"
<< "}";
+
+ // query(odb::query_base)
+ //
+ if (multi_dynamic)
+ os << "result< " << traits << "::view_type >" << endl
+ << traits << "::" << endl
+ << "query (database& db, const odb::query_base& q)"
+ << "{"
+ << "return query (db, query_base_type (q));"
+ << "}";
}
// Prepared. Very similar to unprepared but has some annoying variations
@@ -3691,6 +3706,8 @@ traverse_view (type& c)
//
if (options.generate_prepared ())
{
+ // prepare_query
+ //
os << "odb::details::shared_ptr<prepared_query_impl>" << endl
<< traits << "::" << endl
<< "prepare_query (connection& c, const char* n, " <<
@@ -3737,6 +3754,19 @@ traverse_view (type& c)
<< "return r;"
<< "}";
+ // prepare_query(odb::query_base)
+ //
+ if (multi_dynamic)
+ os << "odb::details::shared_ptr<prepared_query_impl>" << endl
+ << traits << "::" << endl
+ << "prepare_query (connection& c, const char* n, " <<
+ "const odb::query_base& q)"
+ << "{"
+ << "return prepare_query (c, n, query_base_type (q));"
+ << "}";
+
+ // execute_query
+ //
os << "odb::details::shared_ptr<result_impl>" << endl
<< traits << "::" << endl
<< "execute_query (prepared_query_impl& q)"
@@ -3786,6 +3816,40 @@ traverse_view (type& c)
<< "pq.query, st, sts));"
<< "}";
}
+
+ // Generate function table registration for dynamic multi-database
+ // support.
+ //
+ if (multi_dynamic)
+ {
+ string fn (flat_name (type));
+ string dt ("access::view_traits_impl< " + type + ", id_common >");
+
+ os << "static const" << endl
+ << dt << "::" << endl
+ << "function_table_type function_table_" << fn << "_ ="
+ << "{";
+
+ if (!options.omit_unprepared ())
+ os << "&" << traits << "::query";
+
+ if (options.generate_prepared ())
+ {
+ if (!options.omit_unprepared ())
+ os << "," << endl;
+
+ os << "&" << traits << "::prepare_query" << "," << endl
+ << "&" << traits << "::execute_query";
+ }
+
+ os << "};";
+
+ os << "static const view_function_table_entry< " << type << ", " <<
+ "id_" << db << " >" << endl
+ << "function_table_entry_" << fn << "_ (" << endl
+ << "&function_table_" << fn << "_);"
+ << endl;
+ }
}
namespace relational
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index a9c5bb1..ed5f0e3 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -1325,7 +1325,7 @@ namespace relational
else
{
db_type_id = member_database_type_id_->database_type_id (mi.m);
- traits = string (db.string ()) + "::value_traits<\n "
+ traits = db.string () + "::value_traits<\n "
+ type + ",\n "
+ db_type_id + " >";
}
@@ -1643,7 +1643,7 @@ namespace relational
else
{
db_type_id = member_database_type_id_->database_type_id (mi.m);
- traits = string (db.string ()) + "::value_traits<\n "
+ traits = db.string () + "::value_traits<\n "
+ type + ",\n "
+ db_type_id + " >";
}
@@ -3245,6 +3245,8 @@ namespace relational
//
struct persist_statement_params: object_columns_base, virtual context
{
+ typedef persist_statement_params base;
+
persist_statement_params (string& params, query_parameters& qp)
: params_ (params), qp_ (qp)
{
@@ -3292,7 +3294,9 @@ namespace relational
typedef class_ base;
class_ ()
- : grow_base_ (index_),
+ : query_columns_type_ (false, false),
+ view_query_columns_type_ (false),
+ grow_base_ (index_),
grow_member_ (index_),
grow_version_member_ (index_, "version_"),
grow_discriminator_member_ (index_, "discriminator_"),
@@ -3314,6 +3318,8 @@ namespace relational
class_ (class_ const&)
: root_context (), //@@ -Wextra
context (),
+ query_columns_type_ (false, false),
+ view_query_columns_type_ (false),
grow_base_ (index_),
grow_member_ (index_),
grow_version_member_ (index_, "version_"),
@@ -3607,6 +3613,9 @@ namespace relational
}
private:
+ instance<query_columns_type> query_columns_type_;
+ instance<view_query_columns_type> view_query_columns_type_;
+
size_t index_;
instance<grow_base> grow_base_;
traversal::inherits grow_base_inherits_;
@@ -3669,7 +3678,7 @@ namespace relational
if (embedded_schema)
os << "#include <odb/schema-catalog-impl.hxx>" << endl;
- if (options.multi_database () == multi_database::dynamic)
+ if (multi_dynamic)
os << "#include <odb/function-table.hxx>" << endl;
os << endl;
diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx
index 601b01d..ac1de1c 100644
--- a/odb/relational/sqlite/common.cxx
+++ b/odb/relational/sqlite/common.cxx
@@ -166,7 +166,7 @@ namespace relational
struct query_columns: relational::query_columns, context
{
- query_columns (base const& x): base (x) {}
+ query_columns (base const& x): base_impl (x) {}
virtual string
database_type_id (semantics::data_member& m)