diff options
Diffstat (limited to 'odb/relational')
-rw-r--r-- | odb/relational/common-query.cxx | 167 | ||||
-rw-r--r-- | odb/relational/common-query.hxx | 64 | ||||
-rw-r--r-- | odb/relational/common.cxx | 571 | ||||
-rw-r--r-- | odb/relational/common.hxx | 350 | ||||
-rw-r--r-- | odb/relational/header.cxx | 62 | ||||
-rw-r--r-- | odb/relational/header.hxx | 371 | ||||
-rw-r--r-- | odb/relational/mssql/common.cxx | 16 | ||||
-rw-r--r-- | odb/relational/mysql/common.cxx | 2 | ||||
-rw-r--r-- | odb/relational/oracle/common.cxx | 18 | ||||
-rw-r--r-- | odb/relational/pgsql/common.cxx | 2 | ||||
-rw-r--r-- | odb/relational/source.cxx | 178 | ||||
-rw-r--r-- | odb/relational/source.hxx | 17 | ||||
-rw-r--r-- | odb/relational/sqlite/common.cxx | 2 |
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) |