From e56ba020233ad7cb4762df300a6774db9195d817 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 9 Sep 2011 12:18:39 +0200 Subject: New templated query_columns architecture We also now use the correct separate "role"-base join approach instead of having a single merged join for each table. --- odb/relational/header.hxx | 321 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 267 insertions(+), 54 deletions(-) (limited to 'odb/relational/header.hxx') diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 30cb01e..cc89e9a 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -115,14 +115,17 @@ namespace relational }; // - // query_type + // query_columns_type // - struct query_base: traversal::class_, virtual context + struct query_columns_bases: traversal::class_, virtual context { - typedef query_base base; + typedef query_columns_bases base; - query_base (): first_ (true) {} + query_columns_bases (bool ptr, bool first = true) + : ptr_ (ptr), first_ (first) + { + } virtual void traverse (type& c) @@ -143,37 +146,156 @@ namespace relational << " "; } - os << "object_traits< " << c.fq_name () << " >::query_columns"; + os << (ptr_ ? "pointer_query_columns" : "query_columns") << + "< " << c.fq_name () << ", table >"; } private: + bool ptr_; bool first_; }; - struct query_type: traversal::class_, virtual context + struct query_columns_base_aliases: traversal::class_, virtual context { - typedef query_type base; + typedef query_columns_base_aliases base; + + query_columns_base_aliases (bool ptr) + : ptr_ (ptr) + { + } virtual void traverse (type& c) { - os << "struct query_columns"; + // Ignore transient bases. Not used for views. + // + if (!object (c)) + return; - { - instance b; - traversal::inherits i (*b); - inherits (c, i); - } + os << "// " << c.name () << endl + << "//" << endl + << "typedef " << + (ptr_ ? "pointer_query_columns" : "query_columns") << + "< " << c.fq_name () << ", table > " << c.name () << ";" + << endl; + } - os << "{"; + 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 (c.fq_name ()); + + if (ptr_) { - instance t; - t->traverse (c); + os << "template " << endl + << "struct pointer_query_columns< " << type << ", table >"; + + // 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)) + { + os << ":" << endl + << " query_columns< " << type << ", table >" + << "{" + << "};"; + } + else + { + { + instance b (ptr_); + traversal::inherits i (*b); + inherits (c, i); + } + + os << "{"; + + { + instance b (ptr_); + traversal::inherits i (*b); + inherits (c, i); + } + + { + instance t (ptr_); + t->traverse (c); + } + + os << "};"; + + { + instance t (ptr_, c); + t->traverse (c); + } + } } + else + { + bool has_ptr (has_a (c, test_pointer | exclude_base)); - os << "};"; + if (has_ptr) + { + os << "template <>" << endl + << "struct query_columns_base< " << type << " >" + << "{"; + + instance t; + t->traverse (c); + + os << "};"; + } + + os << "template " << endl + << "struct query_columns< " << type << ", table >"; + + if (has_ptr) + os << ":" << endl + << " query_columns_base< " << type << " >"; + + { + instance b (ptr_, !has_ptr); + traversal::inherits i (*b); + inherits (c, i); + } + + os << "{"; + + { + instance b (ptr_); + traversal::inherits i (*b); + inherits (c, i); + } + + { + instance t (ptr_); + t->traverse (c); + } + + os << "};"; + + { + instance t (ptr_, c); + t->traverse (c); + } + } } + + public: + bool ptr_; }; // Member-specific traits types for container members. @@ -368,9 +490,9 @@ namespace relational // Statements. // - os << "static const char* const insert_one_statement;" - << "static const char* const select_all_statement;" - << "static const char* const delete_all_statement;" + os << "static const char insert_one_statement[];" + << "static const char select_all_statement[];" + << "static const char delete_all_statement[];" << endl; } @@ -732,18 +854,26 @@ namespace relational semantics::class_& c_; }; + // First pass over objects, views, and composites. Some code must be + // split into two parts to deal with yet undefined types. // - // - struct class_: traversal::class_, virtual context + struct class1: traversal::class_, virtual context { - typedef class_ base; + typedef class1 base; - class_ (): id_image_member_ ("id_") {} + class1 () + : id_image_member_ ("id_"), + query_columns_type_ (false), + pointer_query_columns_type_ (true) + { + } - class_ (class_ const&) + class1 (class_ const&) : root_context (), //@@ -Wextra context (), - id_image_member_ ("id_") + id_image_member_ ("id_"), + query_columns_type_ (false), + pointer_query_columns_type_ (true) { } @@ -774,7 +904,6 @@ namespace relational virtual void traverse_object (type& c) { - bool abst (abstract (c)); string const& type (c.fq_name ()); semantics::data_member* id (id_member (c)); @@ -784,12 +913,33 @@ namespace relational os << "// " << c.name () << endl << "//" << endl; + // class_traits + // os << "template <>" << endl << "struct class_traits< " << type << " >" << "{" << "static const class_kind kind = class_object;" << "};"; + // pointer_query_columns & query_columns + // + if (options.generate_query ()) + { + // If we don't have object pointers, then also generate + // query_columns (in this case pointer_query_columns and + // query_columns are the same and the former inherits from + // the latter). Otherwise we have to postpone query_columns + // generation until the second pass to deal with forward- + // declared objects. + // + if (!has_a (c, test_pointer)) + query_columns_type_->traverse (c); + + pointer_query_columns_type_->traverse (c); + } + + // object_traits + // os << "template <>" << endl << "class access::object_traits< " << type << " >" << "{" @@ -837,17 +987,6 @@ namespace relational image_type_->traverse (c); // - // Query (abstract and concrete). - // - - if (options.generate_query ()) - { - // query_columns - // - query_type_->traverse (c); - } - - // // Containers (abstract and concrete). // @@ -919,7 +1058,7 @@ namespace relational // // The rest only applies to concrete objects. // - if (abst) + if (abstract (c)) { object_public_extra_post (c); os << "};"; @@ -939,12 +1078,7 @@ namespace relational // query_type // - os << "struct query_type: query_base_type, query_columns" - << "{" - << "query_type ();" - << "query_type (const std::string&);" - << "query_type (const query_base_type&);" - << "};"; + os << "struct query_type;"; } // @@ -966,17 +1100,17 @@ namespace relational // Statements. // - os << "static const char* const persist_statement;" - << "static const char* const find_statement;" - << "static const char* const update_statement;" - << "static const char* const erase_statement;"; + os << "static const char persist_statement[];" + << "static const char find_statement[];" + << "static const char update_statement[];" + << "static const char erase_statement[];"; if (options.generate_query ()) { - os << "static const char* const query_clause;" - << "static const char* const erase_query_clause;" + os << "static const char query_clause[];" + << "static const char erase_query_clause[];" << endl - << "static const char* const table_name;"; + << "static const char table_name[];"; } os << endl; @@ -1184,7 +1318,7 @@ namespace relational // Statements. // - os << "static const char* const query_statement;" + os << "static const char query_statement[];" << endl; // @@ -1272,8 +1406,87 @@ namespace relational private: instance image_type_; - instance query_type_; instance id_image_member_; + + instance query_columns_type_; + instance pointer_query_columns_type_; + }; + + // Second pass over objects, views, and composites. + // + struct class2: traversal::class_, virtual context + { + typedef class2 base; + + class2 (): query_columns_type_ (false) {} + + class2 (class_ const&) + : root_context (), //@@ -Wextra + context (), + query_columns_type_ (false) + { + } + + virtual void + traverse (type& c) + { + if (c.file () != unit.file ()) + return; + + if (object (c)) + traverse_object (c); + else if (view (c)) + traverse_view (c); + else if (composite (c)) + traverse_composite (c); + } + + virtual void + traverse_object (type& c) + { + bool abst (abstract (c)); + string const& type (c.fq_name ()); + + os << "// " << c.name () << endl + << "//" << endl; + + if (options.generate_query ()) + { + // query_columns + // + // If we don't have any pointers, then query_columns is generated + // in pass 1 (see the comment in class1 for details). + // + if (has_a (c, test_pointer)) + query_columns_type_->traverse (c); + + // query_type + // + if (!abst) + os << "struct access::object_traits< " << type << " >::" << + "query_type:" << endl + << " query_base_type," << endl + << " query_columns< " << type << ", table_name >" + << "{" + << "query_type ();" + << "query_type (const std::string&);" + << "query_type (const query_base_type&);" + << "};"; + } + } + + virtual void + traverse_view (type&) + { + } + + virtual void + traverse_composite (type&) + { + } + + private: + instance query_columns_type_; }; struct include: virtual context -- cgit v1.1