From 791b94b894f93bc037637907616efc844f3d9414 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 17 Sep 2013 11:11:43 +0200 Subject: Add support for defining composite values inside persistent classes, etc --- NEWS | 4 ++ doc/manual.xhtml | 24 +++++++++ odb/header.cxx | 54 +++++++++++++++----- odb/include.cxx | 19 ++++++- odb/inline.cxx | 27 ++++++++-- odb/processor.cxx | 17 +++++-- odb/relational/header.hxx | 66 +++++++++++++++++------- odb/relational/inline.hxx | 30 ++++++++--- odb/relational/processor.cxx | 12 ++++- odb/relational/source.hxx | 30 ++++++++--- odb/relational/validator.cxx | 35 ++++++++++--- odb/source.cxx | 25 ++++++--- odb/validator.cxx | 119 ++++++++++++++++++++++++++----------------- 13 files changed, 342 insertions(+), 120 deletions(-) diff --git a/NEWS b/NEWS index c7742fa..51375ce 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ Version 2.3.0 queries. For more information, refer to Section 4.1, "ODB Query Language" in the ODB manual. + * Support for defining composite value types inside persistent classes, + views, or other composite values. For more information, refer to Section + 7.2, "Composite Value Types" in the ODB manual. + * The schema_catalog::create_schema() function now has a third argument which indicates whether to drop the schema prior to creating the new one. The default is true which is backwards-compatible. The schema_catalog diff --git a/doc/manual.xhtml b/doc/manual.xhtml index f754e40..c84f1bc 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -7442,6 +7442,30 @@ class person }; +

A composite value type can be defined inside a persistent class, + view, or another composite value and even made private, provided + we make odb::access a friend of the containing class, + for example:

+ +
+#pragma db object
+class person
+{
+  ...
+
+  #pragma db value
+  class name
+  {
+    ...
+
+    std::string first_;
+    std::string last_;
+  };
+
+  name name_;
+};
+  
+

A composite value type can also be defined as an instantiation of a C++ class template, for example:

diff --git a/odb/header.cxx b/odb/header.cxx index 4c58774..fad1668 100644 --- a/odb/header.cxx +++ b/odb/header.cxx @@ -13,19 +13,31 @@ namespace header struct class1: traversal::class_, virtual context { class1 () - : query_columns_type_ (false, true, false), - pointer_query_columns_type_ (true, true, false) {} + : typedefs_ (false), + query_columns_type_ (false, true, false), + pointer_query_columns_type_ (true, true, false) + { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + } virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + default: break; + } } void @@ -35,6 +47,9 @@ namespace header traverse_view (type&); private: + traversal::defines defines_; + typedefs typedefs_; + instance query_columns_type_; instance pointer_query_columns_type_; }; @@ -645,22 +660,32 @@ namespace header struct class2: traversal::class_, virtual context { class2 () - : query_columns_type_ (false, true, false), + : typedefs_ (false), + query_columns_type_ (false, true, false), query_columns_type_inst_ (false, false, true), view_query_columns_type_ (true) { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + default: break; + } } void @@ -670,6 +695,9 @@ namespace header traverse_view (type&); private: + traversal::defines defines_; + typedefs typedefs_; + instance query_columns_type_; instance query_columns_type_inst_; instance view_query_columns_type_; diff --git a/odb/include.cxx b/odb/include.cxx index a6e8c53..cabef1e 100644 --- a/odb/include.cxx +++ b/odb/include.cxx @@ -70,16 +70,28 @@ namespace struct class_: traversal::class_, context { - class_ (include_map& map): main_file_loc_ (0), map_ (map) {} + class_ (include_map& map) + : typedefs_ (true), main_file_loc_ (0), map_ (map) + { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + } virtual void traverse (type& c) { + class_kind_type ck (class_kind (c)); + + if (ck == class_other) + return; + + names (c); // Check nested classes. + // We only generate things for objects and composite value types. In // particular, we don't care about views since they cannot be used in // definitions of other views, objects, or composite values. // - if (!(object (c) || composite (c))) + if (ck != class_object && ck != class_composite) return; // Not interested in classes that we are generating. @@ -153,6 +165,9 @@ namespace } private: + traversal::defines defines_; + typedefs typedefs_; + location_t main_file_loc_; include_map& map_; }; diff --git a/odb/inline.cxx b/odb/inline.cxx index 036a728..79398c5 100644 --- a/odb/inline.cxx +++ b/odb/inline.cxx @@ -67,16 +67,30 @@ namespace inline_ struct class_: traversal::class_, virtual context { + class_ () + : typedefs_ (false) + { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + } + virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + default: break; + } } void @@ -86,6 +100,9 @@ namespace inline_ traverse_view (type&); private: + traversal::defines defines_; + typedefs typedefs_; + callback_calls callback_calls_; }; } diff --git a/odb/processor.cxx b/odb/processor.cxx index 6730242..4221081 100644 --- a/odb/processor.cxx +++ b/odb/processor.cxx @@ -2005,9 +2005,15 @@ namespace struct class_: traversal::class_, context { class_ () - : std_string_ (0), std_string_hint_ (0), access_ (0) + : typedefs_ (true), + std_string_ (0), + std_string_hint_ (0), + access_ (0) { - *this >> member_names_ >> member_; + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + + member_names_ >> member_; // Resolve the std::string type node. // @@ -2054,6 +2060,8 @@ namespace if (k == class_other) return; + names (c); // Process nested classes. + // Check if odb::access is a friend of this class. // c.set ("friend", access_ != 0 && is_friend (c.tree_node (), access_)); @@ -2068,7 +2076,7 @@ namespace else if (k == class_view) traverse_view_pre (c); - names (c); + names (c, member_names_); if (k == class_object) traverse_object_post (c); @@ -2921,6 +2929,9 @@ namespace } private: + traversal::defines defines_; + typedefs typedefs_; + data_member member_; traversal::names member_names_; diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 12ed8ab..de152ca 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -1156,37 +1156,49 @@ namespace relational typedef class1 base; class1 () - : id_image_member_ ("id_"), + : typedefs_ (false), + id_image_member_ ("id_"), version_image_member_ ("version_"), discriminator_image_member_ ("discriminator_"), query_columns_type_ (false, true, false), pointer_query_columns_type_ (true, true, false) { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } - class1 (class_ const&) + class1 (class1 const&) : root_context (), //@@ -Wextra context (), + typedefs_ (false), id_image_member_ ("id_"), version_image_member_ ("version_"), discriminator_image_member_ ("discriminator_"), query_columns_type_ (false, true, false), pointer_query_columns_type_ (true, true, false) { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); - else if (composite (c)) - traverse_composite (c); + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + case class_composite: traverse_composite (c); break; + default: break; + } } virtual void @@ -1219,6 +1231,9 @@ namespace relational traverse_composite (type&); private: + traversal::defines defines_; + typedefs typedefs_; + instance image_type_; instance id_image_member_; instance version_image_member_; @@ -1235,33 +1250,45 @@ namespace relational typedef class2 base; class2 () - : query_columns_type_ (false, true, false), + : typedefs_ (false), + query_columns_type_ (false, true, false), query_columns_type_inst_ (false, false, true), view_query_columns_type_ (true) { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } - class2 (class_ const&) + class2 (class2 const&) : root_context (), //@@ -Wextra context (), + typedefs_ (false), query_columns_type_ (false, true, false), query_columns_type_inst_ (false, false, true), view_query_columns_type_ (true) { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); - else if (composite (c)) - traverse_composite (c); + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + case class_composite: traverse_composite (c); break; + default: break; + } } virtual void @@ -1311,6 +1338,9 @@ namespace relational } private: + traversal::defines defines_; + typedefs typedefs_; + instance query_columns_type_; instance query_columns_type_inst_; instance view_query_columns_type_; diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx index ed5081d..95b4328 100644 --- a/odb/relational/inline.hxx +++ b/odb/relational/inline.hxx @@ -148,7 +148,8 @@ namespace relational typedef class_ base; class_ () - : get_null_base_ (true), + : typedefs_ (false), + get_null_base_ (true), get_null_member_ (true), set_null_base_ (false), set_null_member_ (false) @@ -159,6 +160,7 @@ namespace relational class_ (class_ const&) : root_context (), //@@ -Wextra context (), + typedefs_ (false), get_null_base_ (true), get_null_member_ (true), set_null_base_ (false), @@ -170,6 +172,9 @@ namespace relational void init () { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + get_null_base_inherits_ >> get_null_base_; get_null_member_names_ >> get_null_member_; @@ -180,17 +185,23 @@ namespace relational virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; + names (c); + context::top_object = context::cur_object = &c; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); - else if (composite (c)) - traverse_composite (c); + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + case class_composite: traverse_composite (c); break; + default: break; + } context::top_object = context::cur_object = 0; } @@ -640,6 +651,9 @@ namespace relational } private: + traversal::defines defines_; + typedefs typedefs_; + instance get_null_base_; traversal::inherits get_null_base_inherits_; instance get_null_member_; diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index 231e4f0..633f4b0 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -992,8 +992,12 @@ namespace relational struct class_: traversal::class_, context { class_ () + : typedefs_ (true) { - *this >> member_names_ >> member_; + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + + member_names_ >> member_; } virtual void @@ -1004,7 +1008,8 @@ namespace relational if (k == class_other) return; - names (c); + names (c); // Process nested classes. + names (c, member_names_); if (k == class_object) traverse_object (c); @@ -1537,6 +1542,9 @@ namespace relational private: cxx_string_lexer lex_; + traversal::defines defines_; + typedefs typedefs_; + data_member member_; traversal::names member_names_; }; diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index ded4781..d4bc7a8 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -5294,7 +5294,8 @@ namespace relational typedef class_ base; class_ () - : query_columns_type_ (false, false, false), + : typedefs_ (false), + query_columns_type_ (false, false, false), view_query_columns_type_ (false), grow_base_ (index_), grow_member_ (index_), @@ -5318,6 +5319,7 @@ namespace relational class_ (class_ const&) : root_context (), //@@ -Wextra context (), + typedefs_ (false), query_columns_type_ (false, false, false), view_query_columns_type_ (false), grow_base_ (index_), @@ -5342,6 +5344,9 @@ namespace relational void init () { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + if (generate_grow) { grow_base_inherits_ >> grow_base_; @@ -5379,17 +5384,23 @@ namespace relational virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; + names (c); + context::top_object = context::cur_object = &c; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); - else if (composite (c)) - traverse_composite (c); + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + case class_composite: traverse_composite (c); break; + default: break; + } context::top_object = context::cur_object = 0; } @@ -5692,6 +5703,9 @@ namespace relational } private: + traversal::defines defines_; + typedefs typedefs_; + instance query_columns_type_; instance view_query_columns_type_; diff --git a/odb/relational/validator.cxx b/odb/relational/validator.cxx index 2a8e04e..c620a58 100644 --- a/odb/relational/validator.cxx +++ b/odb/relational/validator.cxx @@ -237,27 +237,43 @@ namespace relational { class2 (bool& valid) : valid_ (valid), + typedefs_ (true), data_member_ (valid), object_no_id_members_ (valid), composite_id_members_ (valid), view_members_ (valid) { - *this >> data_member_names_ >> data_member_; + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + + data_member_names_ >> data_member_; } virtual void traverse (type& c) { - if (object (c)) + class_kind_type ck (class_kind (c)); + switch (ck) + { + case class_object: + names (c); traverse_object (c); - else if (view (c)) + break; + case class_view: + names (c); traverse_view (c); - else if (composite (c)) + break; + case class_composite: + names (c); traverse_composite (c); + break; + case class_other: + break; + } // Make sure indexes are not defined for anything other than objects. // - if (c.count ("index") && !object (c)) + if (c.count ("index") && ck != class_object) { indexes& ins (c.get ("index")); @@ -331,7 +347,7 @@ namespace relational } } - names (c); + names (c, data_member_names_); // Validate indexes. // @@ -373,18 +389,21 @@ namespace relational // view_members_.traverse (c); - names (c); + names (c, data_member_names_); } virtual void traverse_composite (type& c) { - names (c); + names (c, data_member_names_); } public: bool& valid_; + traversal::defines defines_; + typedefs typedefs_; + data_member2 data_member_; traversal::names data_member_names_; diff --git a/odb/source.cxx b/odb/source.cxx index a20e5d4..7ea31b4 100644 --- a/odb/source.cxx +++ b/odb/source.cxx @@ -14,21 +14,31 @@ namespace source struct class_: traversal::class_, virtual context { class_ () - : query_columns_type_ (false, false, false), + : typedefs_ (false), + query_columns_type_ (false, false, false), view_query_columns_type_ (false) { + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } virtual void traverse (type& c) { - if (!options.at_once () && class_file (c) != unit.file ()) + class_kind_type ck (class_kind (c)); + + if (ck == class_other || + (!options.at_once () && class_file (c) != unit.file ())) return; - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + default: break; + } } void @@ -38,6 +48,9 @@ namespace source traverse_view (type&); private: + traversal::defines defines_; + typedefs typedefs_; + instance query_columns_type_; instance view_query_columns_type_; }; diff --git a/odb/validator.cxx b/odb/validator.cxx index 2de8882..172ca6d 100644 --- a/odb/validator.cxx +++ b/odb/validator.cxx @@ -396,8 +396,6 @@ namespace // struct value_type: traversal::type, context { - value_type (bool& valid): valid_ (valid) {} - virtual void traverse (semantics::type& t) { @@ -406,33 +404,62 @@ namespace override_null (t); override_null (t, "value"); } + }; - bool& valid_; + struct typedefs1: typedefs + { + typedefs1 (traversal::declares& d) + : typedefs (true), declares_ (d) + { + } + + void + traverse (semantics::typedefs& t) + { + if (check (t)) + traversal::typedefs::traverse (t); + else + declares_.traverse (t); + } + + private: + traversal::declares& declares_; }; // // struct class1: traversal::class_, context { - class1 (bool& valid, value_type& vt) - : valid_ (valid), vt_ (vt), member_ (valid) + class1 (bool& valid) + : valid_ (valid), typedefs_ (declares_), member_ (valid) { - *this >> names_ >> member_; + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; + *this >> declares_ >> vt_; + + names_member_ >> member_; } virtual void traverse (type& c) { - if (object (c)) + switch (class_kind (c)) + { + case class_object: + names (c); traverse_object (c); - else if (view (c)) + break; + case class_view: + names (c); traverse_view (c); - else - { - if (composite (c)) - traverse_composite (c); - + break; + case class_composite: + names (c); + traverse_composite (c); + // Fall through. + case class_other: vt_.dispatch (c); + break; } } @@ -574,7 +601,7 @@ namespace // Check members. // - names (c); + names (c, names_member_); // Check special members. // @@ -881,7 +908,7 @@ namespace // Check members. // - names (c); + names (c, names_member_); // Check id. // @@ -953,7 +980,7 @@ namespace // Check members. // - names (c); + names (c, names_member_); // Check id. // @@ -986,30 +1013,14 @@ namespace } bool& valid_; - value_type& vt_; - - data_member1 member_; - traversal::names names_; - }; - - struct typedefs1: typedefs - { - typedefs1 (traversal::declares& d) - : typedefs (true), declares_ (d) - { - } - void - traverse (semantics::typedefs& t) - { - if (check (t)) - traversal::typedefs::traverse (t); - else - declares_.traverse (t); - } + traversal::defines defines_; + traversal::declares declares_; + typedefs1 typedefs_; - private: - traversal::declares& declares_; + value_type vt_; + data_member1 member_; + traversal::names names_member_; }; // @@ -1180,7 +1191,7 @@ namespace struct class2: traversal::class_, context { class2 (bool& valid) - : valid_ (valid), has_lt_operator_ (0) + : valid_ (valid), has_lt_operator_ (0), typedefs_ (true) { // Find the has_lt_operator function template. // @@ -1218,17 +1229,28 @@ namespace if (has_lt_operator_ == 0) valid_ = false; + + *this >> defines_ >> *this; + *this >> typedefs_ >> *this; } virtual void traverse (type& c) { - if (object (c)) - traverse_object (c); - else if (view (c)) - traverse_view (c); - else if (composite (c)) - traverse_composite (c); + class_kind_type ck (class_kind (c)); + + if (ck == class_other) + return; + + names (c); + + switch (ck) + { + case class_object: traverse_object (c); break; + case class_view: traverse_view (c); break; + case class_composite: traverse_composite (c); break; + default: break; + } // Check version dependencies. // @@ -1415,6 +1437,9 @@ namespace bool& valid_; tree has_lt_operator_; + + traversal::defines defines_; + typedefs typedefs_; }; } @@ -1478,8 +1503,8 @@ validate (options const& ops, traversal::declares unit_declares; typedefs1 unit_typedefs (unit_declares); traversal::namespace_ ns; - value_type vt (valid); - class1 c (valid, vt); + value_type vt; + class1 c (valid); unit >> unit_defines >> ns; unit_defines >> c; -- cgit v1.1