summaryrefslogtreecommitdiff
path: root/odb/common-query.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/common-query.cxx')
-rw-r--r--odb/common-query.cxx1414
1 files changed, 0 insertions, 1414 deletions
diff --git a/odb/common-query.cxx b/odb/common-query.cxx
deleted file mode 100644
index ea45ec3..0000000
--- a/odb/common-query.cxx
+++ /dev/null
@@ -1,1414 +0,0 @@
-// file : odb/common-query.cxx
-// copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <sstream>
-
-#include <odb/common-query.hxx>
-
-using namespace std;
-
-// query_utils
-//
-
-string query_utils::
-depth_suffix (size_t d)
-{
- if (d != 0)
- {
- ostringstream os;
- os << d;
- return '_' + os.str ();
- }
-
- return string ();
-}
-
-// Collect nested (composite) types as generated by query_columns.
-//
-struct query_nested_types: object_columns_base, virtual context
-{
- query_nested_types (bool ptr): ptr_ (ptr), in_ptr_ (false), depth_ (0) {}
-
- virtual void
- traverse_object (semantics::class_& c)
- {
- // We don't want to traverse bases.
- //
- names (c);
- }
-
- virtual void
- traverse_composite (semantics::data_member* m, semantics::class_& c)
- {
- if (m != 0)
- {
- string name (prefix_ + public_name (*m));
- name += in_ptr_ ? "_column_class" : "_class";
- name += query_utils::depth_suffix (depth_);
- name += '_';
- types.push_back (name);
-
- depth_++;
- string p (prefix_);
- prefix_ = name + "::";
- object_columns_base::traverse_composite (m, c);
- prefix_ = p;
- depth_--;
- }
- else
- object_columns_base::traverse_composite (m, c); // Base
- }
-
- virtual void
- traverse_pointer (semantics::data_member& m, semantics::class_& c)
- {
- // The same logic as in query_columns.
- //
- if (inverse (m, key_prefix_))
- return;
-
- bool poly_ref (m.count ("polymorphic-ref"));
-
- if (composite_wrapper (utype (*id_member (c))))
- {
- if (ptr_ || poly_ref)
- object_columns_base::traverse_pointer (m, c);
- else
- {
- in_ptr_ = true;
- object_columns_base::traverse_pointer (m, c);
- in_ptr_ = false;
- }
- }
- }
-
-public:
- strings types;
-
-protected:
- bool ptr_;
- bool in_ptr_; // True while we are "inside" an object pointer.
- string prefix_;
- size_t depth_;
-};
-
-void query_utils::
-inst_query_columns (bool decl,
- bool ptr,
- string const& type,
- string const& alias,
- semantics::class_& c)
-{
- inst_header (decl);
- os << (ptr ? "pointer_" : "") << "query_columns<" << endl
- << " " << type << "," << endl
- << " id_" << db << "," << endl
- << " " << alias << " >;"
- << endl;
-
- // If we are generating extern declarations, we also have to generate
- // them for all the nested (composite) structs. That's what VC++ needs.
- //
- if (decl)
- {
- query_nested_types t (ptr);
- t.traverse (c);
-
- for (strings::iterator i (t.types.begin ()); i != t.types.end (); ++i)
- {
- inst_header (decl, true); // Omit export, GCC doesn't like it.
- os << (ptr ? "pointer_" : "") << "query_columns<" << endl
- << " " << type << "," << endl
- << " id_" << db << "," << endl
- << " " << alias << " >::" << *i << ";"
- << endl;
- }
- }
-}
-
-// query_tags
-//
-
-void query_tags::
-traverse (semantics::class_& c)
-{
- if (object (c) || composite (c))
- {
- object_columns_base::traverse (c);
- }
- else if (view (c))
- {
- if (c.get<size_t> ("object-count") != 0)
- {
- view_objects& objs (c.get<view_objects> ("objects"));
-
- 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;
-
- generate (i->alias);
- }
- }
- }
- // Otherwise it is a transient base (of a composite value).
-
- if (nl_)
- os << endl;
-}
-
-void query_tags::
-traverse_object (semantics::class_& c)
-{
- names (c); // We don't want to traverse bases.
-}
-
-void query_tags::
-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;
-
- if (nl_)
- os << endl;
-
- os << "struct " << public_name (*m) << "_tag" <<
- query_utils::depth_suffix (depth_)
- << "{";
-
- depth_++;
- object_columns_base::traverse_composite (m, c);
- depth_--;
-
- os << "};";
-
- nl_ = false;
-}
-
-void query_tags::
-traverse_pointer (semantics::data_member& m, semantics::class_&)
-{
- // Ignore polymorphic id references.
- //
- if (m.count ("polymorphic-ref"))
- return;
-
- generate (public_name (m));
-}
-
-void query_tags::
-generate (string const& name)
-{
- os << "struct " << name << "_tag;";
- nl_ = true;
-}
-
-// query_alias_traits
-//
-
-query_alias_traits::
-query_alias_traits (semantics::class_& c, bool decl)
- : decl_ (decl), depth_ (0)
-{
- 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" +
- query_utils::depth_suffix (depth_);
-
- depth_++;
- object_columns_base::traverse_composite (m, c);
- depth_--;
-
- scope_ = old_scope;
-}
-
-void query_alias_traits::
-traverse_pointer (semantics::data_member& m, semantics::class_& c)
-{
- // Ignore polymorphic id references.
- //
- if (m.count ("polymorphic-ref"))
- return;
-
- if (decl_)
- generate_decl (public_name (m), c);
- else
- generate_def (m, c);
-}
-
-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);
-
- string const& fq_name (class_fq_name (c));
-
- os << "template <>" << endl
- << "struct " << exp << "alias_traits<" << endl
- << " " << fq_name << "," << endl
- << " id_" << db << "," << endl
- << " " << scope_ << "::" << tag << "_tag>"
- << "{";
-
- if (poly_derived)
- os << "typedef alias_traits<" << endl
- << " " << class_fq_name (*poly_base) << "," << endl
- << " id_" << db << "," << endl
- << " " << scope_ << "::" << tag << "_tag>" << endl
- << "base_traits;"
- << endl;
-
- // For dynamic multi-database support also generate common traits
- // alias. Note that the tag type is the same since they all are
- // derived from object_traits.
- //
- if (db != database::common && multi_dynamic)
- os << "typedef alias_traits<" << endl
- << " " << fq_name << "," << endl
- << " id_common," << endl
- << " " << scope_ << "::" << tag << "_tag>" << endl
- << "common_traits;"
- << endl;
-
- generate_decl_body (); // Table name, etc.
-
- os << "};";
-}
-
-void query_alias_traits::
-generate_decl_body ()
-{
-}
-
-void query_alias_traits::
-generate_def (semantics::data_member&, semantics::class_&)
-{
-}
-
-void query_alias_traits::
-generate_def (string const&, semantics::class_&, string const&)
-{
-}
-
-// query_columns_base
-//
-
-query_columns_base::
-query_columns_base (semantics::class_& c, bool decl, bool inst)
- : decl_ (decl), inst_ (inst), depth_ (0)
-{
- string const& n (class_fq_name (c));
-
- if (decl)
- scope_ = "access::object_traits_impl< " + n + ", id_" +
- db.string () + " >";
- else
- scope_ = "query_columns_base< " + 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));
- string dsuffix (query_utils::depth_suffix (depth_));
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl
- << "struct " << name << "_base" << dsuffix << '_'
- << "{";
-
- string old_scope (scope_);
- scope_ += "::" + name + "_tag" + dsuffix;
-
- depth_++;
- object_columns_base::traverse_composite (m, c);
- depth_--;
-
- scope_ = old_scope;
-
- os << "};";
- }
- else
- {
- string old_scope (scope_);
- scope_ += "::" + name + "_base" + dsuffix + '_';
-
- depth_++;
- object_columns_base::traverse_composite (m, c);
- depth_--;
-
- 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));
- string const& fq_name (class_fq_name (c));
- bool inv (inverse (m, key_prefix_));
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl;
-
- os << "typedef" << endl
- << "odb::alias_traits<" << endl
- << " " << fq_name << "," << endl
- << " id_" << db << "," << endl
- << " " << 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 (inst_)
- {
- generate_inst (m, c);
- }
- else
- {
- // Generate explicit template instantiation directive for the
- // pointed-to pointer_query_columns.
- //
- if (multi_dynamic)
- generate_inst (m, c);
-
- if (inv)
- os << const_ << scope_ << "::" << name << "_type_" << endl
- << scope_ << "::" << name << ";"
- << endl;
- }
-}
-
-void query_columns_base::
-generate_inst (semantics::data_member& m, semantics::class_& c)
-{
- string name (public_name (m));
- string const& fq_name (class_fq_name (c));
-
- string alias (scope_ + "::" + name + "_alias_");
-
- // Instantiate base [pointer_]query_columns.
- //
- {
- instance<query_columns_base_insts> b (true, inst_, alias, true);
- traversal::inherits i (*b);
- inherits (c, i);
- }
-
- // If the pointed-to class has no pointers of its own then
- // pointer_query_columns just derives from query_columns and
- // that's what we need to instantiate.
- //
- inst_query_columns (inst_,
- has_a (c, test_pointer | include_base),
- fq_name,
- alias,
- c);
-}
-
-// query_columns
-//
-
-query_columns::
-query_columns (bool decl, bool ptr, semantics::class_& c)
- : decl_ (decl), ptr_ (ptr), poly_ref_ (false), in_ptr_ (false),
- fq_name_ (class_fq_name (c)),
- resue_abstract_ (abstract (c) && !polymorphic (c)),
- depth_ (0)
-{
-}
-
-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;
- }
-
- // Use _class_ instead of _type_ to avoid potential clashes between
- // the class and member names.
- //
- string name (public_name (*m));
- string suffix (in_ptr_ ? "_column_class" : "_class");
-
- // Add depth to the nested composite to avoid potential name conflicts
- // in situations like these:
- //
- // struct inner { ... };
- // struct outer { inner value; };
- // struct object { outer value; }
- //
- string dsuffix (query_utils::depth_suffix (depth_));
- suffix += dsuffix;
- suffix += '_';
-
- depth_++;
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl
- << "struct ";
-
- // For some bizarre reason VC++ needs the export directive for
- // a type nested in an (exported) template. This appears not
- // to cause any problems for GCC.
- //
- // We only generate the export directive if we are also
- // explicitly instantiating the query_columns templates.
- //
- if (multi_dynamic && !resue_abstract_)
- os << exp;
-
- os << name << suffix;
-
- // Derive from the base in query_columns_base. It contains columns
- // data for the pointer members.
- //
- if (!ptr_ && !poly_ref_ && has_a (c, test_pointer))
- os << ": " << name << "_base" << dsuffix << '_';
-
- os << "{";
-
- if (!const_.empty ())
- os << name << suffix << " ()" // Need user-defined default c-tor for
- << "{" // initialization of static const.
- << "}";
-
- object_columns_base::traverse_composite (m, c);
-
- os << "};";
-
- if (!in_ptr_)
- os << "static " << const_ << name << suffix << " " << 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 for the in-
- // pointer case because the actual pointer column type derives from
- // the composite column type (dual interface; see traverse_pointer()
- // below).
- //
- 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 <<
- (in_ptr_ ? string ("_type_") : suffix) << endl
- << tmpl << "::" << name << ";"
- << endl;
- }
-
- depth_--;
-}
-
-void query_columns::
-column_ctor (string const&, string const&, string const&)
-{
-}
-
-void query_columns::
-column_common (semantics::data_member& m,
- string const& type,
- string const&,
- string const& suffix)
-{
- string name (public_name (m));
-
- if (decl_)
- {
- os << "// " << name << endl
- << "//" << endl;
-
- os << "typedef odb::query_column< " << type << " > " << 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 << "::" << name << ";"
- << endl;
- }
-}
-
-bool query_columns::
-traverse_column (semantics::data_member& m, string const& column, bool)
-{
- semantics::names* hint;
- semantics::type* t (&utype (m, hint));
-
- // Unwrap it if it is a wrapper.
- //
- if (semantics::type* wt = wrapper (*t, hint))
- t = &utype (*wt, 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)
-{
- // 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;
-
- // If we ignore polymorphic references, then a view that uses a custom
- // join condition based on id will use the id column from the base
- // table. But the base table hasn't been joined yet. To resolve this
- // we will generate the id member that points to our column.
- //
- poly_ref_ = m.count ("polymorphic-ref");
-
- string name (public_name (m));
-
- data_member_path& id (*id_member (c));
- semantics::names* hint;
- semantics::type& t (utype (id, hint));
-
- if (composite_wrapper (t))
- {
- // Composite id.
- //
-
- // For pointer_query_columns and poly refs generate normal composite
- // mapping.
- //
- if (ptr_ || poly_ref_)
- 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_class" << query_utils::depth_suffix (depth_) << '_'
- << "{";
-
- if (!const_.empty ())
- os << name << "_type_ ()" // Need user-defined default c-tor for
- << "{" // initialization of static const.
- << "}";
-
- os << "};";
-
- os << "static " << const_ << name << "_type_ " << name << ";"
- << endl;
- }
- }
- }
- else
- {
- // Simple id.
- //
- string type (t.fq_name (hint));
- string col (column_name (m, key_prefix_, default_name_, column_prefix_));
-
- // For pointer_query_columns and poly refs generate normal column mapping.
- //
- if (ptr_ || poly_ref_)
- column_common (m, type, col);
- 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, col, "_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_"
- << "{";
-
- column_ctor (type, name + "_type_", name + "_column_type_");
-
- os << "};";
- }
- }
-
- if (decl_)
- os << "static " << const_ << name << "_type_ " << name << ";"
- << endl;
- }
-
- poly_ref_ = false;
-}
-
-// query_columns_bases
-//
-
-void query_columns_bases::
-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 << " >";
-}
-
-// query_columns_base_aliases
-//
-
-void query_columns_base_aliases::
-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;
-}
-
-// query_columns_base_insts
-//
-
-query_columns_base_insts::
-query_columns_base_insts (bool test_ptr,
- bool decl,
- string const& alias,
- bool poly)
- : test_ptr_ (test_ptr), decl_ (decl), alias_ (alias), poly_ (poly)
-{
- *this >> inherits_ >> *this;
-}
-
-query_columns_base_insts::
-query_columns_base_insts (query_columns_base_insts const& x)
- : context (), // @@ -Wextra
- test_ptr_ (x.test_ptr_),
- decl_ (x.decl_),
- alias_ (x.alias_),
- poly_ (x.poly_)
-{
- *this >> inherits_ >> *this;
-}
-
-void query_columns_base_insts::
-traverse (type& c)
-{
- if (!object (c))
- return;
-
- bool poly (polymorphic (c));
- if (poly && (poly != poly_))
- return;
-
- bool ptr (has_a (c, test_pointer | include_base));
-
- string old_alias;
- if (poly)
- {
- old_alias = alias_;
- alias_ += "::base_traits";
- }
-
- // Instantiate bases recursively.
- //
- inherits (c, inherits_);
-
- inst_query_columns (decl_,
- test_ptr_ && ptr,
- class_fq_name (c),
- alias_,
- c);
-
- if (!test_ptr_ && ptr)
- inst_query_columns (decl_, true, class_fq_name (c), alias_, c);
-
- if (poly)
- alias_ = old_alias;
-}
-
-// query_columns_type
-//
-
-void query_columns_type::
-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);
- }
-
- {
- bool true_ (true);
- instance<query_columns> t (true_, ptr_, c); //@@ forwarding
- t->traverse (c);
- }
-
- os << "};";
-
- generate_impl (c);
- }
- }
- else if (decl_)
- {
- bool has_ptr (has_a (c, test_pointer | exclude_base));
-
- if (has_ptr)
- {
- // Generate aliases.
- //
- {
- bool true_ (true); //@@ (im)perfect forwarding
- instance<query_alias_traits> t (c, true_);
- t->traverse (c);
- }
-
- // 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 " << exp << "query_columns_base< " << type << ", " <<
- "id_" << db << " >"
- << "{";
-
- bool true_ (true); //@@ (im)perfect forwarding.
- bool false_ (false);
- instance<query_columns_base> t (c, true_, false_);
- 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 (decl_, ptr_, c);
- t->traverse (c);
- }
-
- os << "};";
-
- generate_impl (c);
- }
- else if (inst_)
- {
- // If we have the extern symbol, generate extern template declarations.
- //
- if (!ext.empty ())
- {
- bool has_ptr (has_a (c, test_pointer | exclude_base));
- bool reuse_abst (abstract (c) && !polymorphic (c));
-
- if (has_ptr || !reuse_abst)
- {
- os << "#ifdef " << ext << endl
- << endl;
-
- if (has_ptr)
- {
- bool true_ (true); //@@ (im)perfect forwarding.
- bool false_ (false);
-
- instance<query_columns_base> t (c, false_, true_);
- t->traverse (c);
- }
-
- // Don't generate it for reuse-abstract classes.
- //
- if (!reuse_abst)
- generate_inst (c);
-
- os << "#endif // " << ext << endl
- << endl;
- }
- }
- }
- else
- {
- 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_, false_);
- t->traverse (c);
- }
-
- // Explicit template instantiations. Don't generate it for reuse-
- // abstract classes.
- //
- if (multi_dynamic && (!abstract (c) || polymorphic (c)))
- generate_inst (c);
- }
-}
-
-void query_columns_type::
-generate_impl (type& c)
-{
- string guard;
-
- // Exclude definitions (they will be explicitly instantiated once in
- // the source file) unless we have the extern symbol. In this case
- // the extern template declaration will make sure we don't get
- // instantiations in multiple places and we will avoid the VC++
- // warning C4661 (no definition provided).
- //
- if (multi_dynamic && ext.empty ())
- {
- guard = make_guard ("ODB_" + db.string () + "_QUERY_COLUMNS_DEF");
-
- os << "#ifdef " << guard << endl
- << endl;
- }
-
- {
- bool false_ (false);
- instance<query_columns> t (false_, ptr_, c);
- t->traverse (c);
- }
-
- if (!guard.empty ())
- os << "#endif // " << guard << endl
- << endl;
-}
-
-void query_columns_type::
-generate_inst (type& c)
-{
- string const& type (class_fq_name (c));
-
- // Explicit template instantiations. Here is what we need to
- // instantiate
- //
- // 1. Reuse inheritance bases all the way to the ultimate base.
- // Unlike poly inheritance, reuse inheritance uses the table
- // alias of the derived type. Note that bases can have object
- // pointers of their own but their types have already been
- // instantiated by step 3 below performed for the base object.
- //
- // 2. Object pointers. Note that while object pointers cannot have
- // their own pointers, they can have reuse inheritance bases.
- //
- // 3. The query_columns class for the table itself.
- //
- // We also need to repeat these steps for pointer_query_columns
- // since it is used by views.
- //
- string alias ("access::object_traits_impl< " + type + ", id_" +
- db.string () + " >");
-
- // 1
- //
- {
- instance<query_columns_base_insts> b (false, inst_, alias, false);
- traversal::inherits i (*b);
- inherits (c, i);
- }
-
- // 2: Handled by query_columns_base (which is where we generate
- // all the aliases for object pointers).
- //
-
- // 3
- //
- inst_query_columns (inst_, false, type, alias, c);
-
- if (has_a (c, test_pointer | exclude_base))
- inst_query_columns (inst_, true, type, alias, c);
-}
-
-// view_query_columns_type
-//
-
-void view_query_columns_type::
-traverse (type& c)
-{
- if (decl_)
- generate_decl (c);
- else
- generate_def (c);
-}
-
-void view_query_columns_type::
-generate_decl (type& c)
-{
- string const& type (class_fq_name (c));
- size_t obj_count (c.get<size_t> ("object-count"));
- 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);
- }
- }
-
- // If we have the extern symbol, generate extern template declarations.
- // Do it before query_columns since the inheritance will trigger
- // instantiation and we won't be able to change visibility (GCC).
- //
- if (obj_count != 0 && multi_dynamic && !ext.empty ())
- {
- os << "#ifdef " << ext << endl
- << endl;
-
- generate_inst (c);
-
- os << "#endif // " << ext << endl
- << endl;
- }
-
- // query_columns
- //
- os << "struct " << exp << "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 << "{"
- << "};";
- }
-}
-
-void view_query_columns_type::
-generate_def (type& c)
-{
- 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);
- }
- }
- }
-
- if (multi_dynamic)
- generate_inst (c);
-}
-
-void view_query_columns_type::
-generate_inst (type& c)
-{
- string const& type (class_fq_name (c));
- view_objects& objs (c.get<view_objects> ("objects"));
-
- string traits ("access::view_traits_impl< " + type + ", id_" +
- db.string () + " >");
-
- // Instantiate [pointer_]query_columns.
- //
- 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; // Instantiated by object.
-
- 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 ())
- {
- string const& otype (class_fq_name (o));
- string alias ("odb::alias_traits<\n"
- " " + otype + ",\n"
- " id_" + db.string () + ",\n"
- " " + traits + "::" + i->alias + "_tag>");
-
- // Instantiate base [pointer_]query_columns.
- //
- {
- instance<query_columns_base_insts> b (true, decl_, alias, true);
- traversal::inherits i (*b);
- inherits (o, i);
- }
-
- // If the pointed-to class has no pointers of its own then
- // pointer_query_columns just derives from query_columns and
- // that's what we need to instantiate.
- //
- inst_query_columns (decl_,
- has_a (o, test_pointer | include_base),
- otype,
- alias,
- o);
- }
- }
-}