aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/common-query.cxx166
-rw-r--r--odb/common-query.hxx18
-rw-r--r--odb/context.cxx4
-rw-r--r--odb/context.hxx2
4 files changed, 139 insertions, 51 deletions
diff --git a/odb/common-query.cxx b/odb/common-query.cxx
index 4f5a43f..2d8ad98 100644
--- a/odb/common-query.cxx
+++ b/odb/common-query.cxx
@@ -6,6 +6,105 @@
using namespace std;
+// query_utils
+//
+
+// 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) {}
+
+ 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_type_" : "_type_";
+ types.push_back (name);
+
+ string p (prefix_);
+ prefix_ += name + "::";
+ object_columns_base::traverse_composite (m, c);
+ prefix_ = p;
+ }
+ 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 (m.count ("polymorphic-ref") || inverse (m, key_prefix_))
+ return;
+
+ if (composite_wrapper (utype (*id_member (c))))
+ {
+ if (ptr_)
+ 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_;
+};
+
+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
//
@@ -350,13 +449,11 @@ generate_inst (semantics::data_member& m, semantics::class_& c)
// pointer_query_columns just derives from query_columns and
// that's what we need to instantiate.
//
- inst_header (inst_);
- os << (has_a (c, test_pointer | include_base) ? "pointer_" : "") <<
- "query_columns<" << endl
- << " " << fq_name << "," << endl
- << " id_" << db << "," << endl
- << " " << alias << " >;"
- << endl;
+ inst_query_columns (inst_,
+ has_a (c, test_pointer | include_base),
+ fq_name,
+ alias,
+ c);
}
// query_columns
@@ -398,9 +495,13 @@ traverse_composite (semantics::data_member* m, semantics::class_& c)
if (decl_)
{
+ // 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.
+ //
os << "// " << name << endl
<< "//" << endl
- << "struct " << name << suffix;
+ << "struct " << exp << name << suffix;
// Derive from the base in query_columns_base. It contains columns
// data for the pointer members.
@@ -733,23 +834,14 @@ traverse (type& c)
//
inherits (c, inherits_);
- inst_header (decl_);
- os << (test_ptr_ && ptr ? "pointer_query_columns" : "query_columns") <<
- "<" << endl
- << " " << class_fq_name (c) << "," << endl
- << " id_" << db << "," << endl
- << " " << alias_ << " >;"
- << endl;
+ inst_query_columns (decl_,
+ test_ptr_ && ptr,
+ class_fq_name (c),
+ alias_,
+ c);
if (!test_ptr_ && ptr)
- {
- inst_header (decl_);
- os << "pointer_query_columns<" << endl
- << " " << class_fq_name (c) << "," << endl
- << " id_" << db << "," << endl
- << " " << alias_ << " >;"
- << endl;
- }
+ inst_query_columns (decl_, true, class_fq_name (c), alias_, c);
if (poly)
alias_ = old_alias;
@@ -996,22 +1088,10 @@ generate_inst (type& c)
// 3
//
- inst_header (inst_);
- os << "query_columns<" << endl
- << " " << type << "," << endl
- << " id_" << db << "," << endl
- << " " << alias << " >;"
- << endl;
+ inst_query_columns (inst_, false, type, alias, c);
if (has_a (c, test_pointer | exclude_base))
- {
- inst_header (inst_);
- os << "pointer_query_columns<" << endl
- << " " << type << "," << endl
- << " id_" << db << "," << endl
- << " " << alias << " >;"
- << endl;
- }
+ inst_query_columns (inst_, true, type, alias, c);
}
// view_query_columns_type
@@ -1250,13 +1330,11 @@ generate_inst (type& c)
// pointer_query_columns just derives from query_columns and
// that's what we need to instantiate.
//
- inst_header (decl_);
- os << (has_a (o, test_pointer | include_base) ? "pointer_" : "") <<
- "query_columns<" << endl
- << " " << otype << "," << endl
- << " id_" << db << "," << endl
- << " " << alias << " >;"
- << endl;
+ inst_query_columns (decl_,
+ has_a (o, test_pointer | include_base),
+ otype,
+ alias,
+ o);
}
}
}
diff --git a/odb/common-query.hxx b/odb/common-query.hxx
index b340b9f..5b0f71b 100644
--- a/odb/common-query.hxx
+++ b/odb/common-query.hxx
@@ -12,6 +12,16 @@
// Query-related generators.
//
+struct query_utils: virtual context
+{
+ void
+ inst_query_columns (bool decl, // Extern declaration or instanatiation.
+ bool ptr, // pointer_query_columns or query_columns
+ string const& type, // Object fq-type.
+ string const& alias, // Table alias.
+ semantics::class_&); // Traverse for nested structs.
+};
+
// Generate query tags for pointers in this objects.
//
struct query_tags: object_columns_base, virtual context
@@ -75,7 +85,7 @@ protected:
// Generate query columns in the query_columns_base class.
//
-struct query_columns_base: object_columns_base, virtual context
+struct query_columns_base: object_columns_base, query_utils
{
typedef query_columns_base base;
@@ -179,7 +189,7 @@ private:
// Generate explicit instantiations of base classes.
//
-struct query_columns_base_insts: traversal::class_, virtual context
+struct query_columns_base_insts: traversal::class_, query_utils
{
typedef query_columns_base_insts base;
@@ -203,7 +213,7 @@ private:
// Generate the query_columns_base/query_columns or pointer_query_columns
// classes for objects.
//
-struct query_columns_type: traversal::class_, virtual context
+struct query_columns_type: traversal::class_, query_utils
{
typedef query_columns_type base;
@@ -237,7 +247,7 @@ public:
// Generate the query_columns class for views.
//
-struct view_query_columns_type: traversal::class_, virtual context
+struct view_query_columns_type: traversal::class_, query_utils
{
typedef view_query_columns_type base;
diff --git a/odb/context.cxx b/odb/context.cxx
index 352cb51..ef6ef9c 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -2345,14 +2345,14 @@ strlit (string const& str)
}
void context::
-inst_header (bool decl)
+inst_header (bool decl, bool omit_exp)
{
if (decl && !ext.empty ())
os << ext << " ";
os << "template struct";
- if (!exp.empty ())
+ if (!omit_exp && !exp.empty ())
{
// If we are generating an explicit instantiation directive rather
// than the extern template declaration, then omit the export symbol
diff --git a/odb/context.hxx b/odb/context.hxx
index e0238dd..41428d0 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -1227,7 +1227,7 @@ public:
// extern and export symbols.
//
void
- inst_header (bool decl);
+ inst_header (bool decl, bool omit_exp = false);
// Counts and other information.
//