diff options
Diffstat (limited to 'odb/relational')
-rw-r--r-- | odb/relational/common.cxx | 24 | ||||
-rw-r--r-- | odb/relational/common.hxx | 2 | ||||
-rw-r--r-- | odb/relational/header.cxx | 435 | ||||
-rw-r--r-- | odb/relational/header.hxx | 256 | ||||
-rw-r--r-- | odb/relational/inline.hxx | 186 | ||||
-rw-r--r-- | odb/relational/mssql/common.cxx | 3 | ||||
-rw-r--r-- | odb/relational/mysql/common.cxx | 3 | ||||
-rw-r--r-- | odb/relational/mysql/source.cxx | 2 | ||||
-rw-r--r-- | odb/relational/oracle/common.cxx | 3 | ||||
-rw-r--r-- | odb/relational/pgsql/common.cxx | 3 | ||||
-rw-r--r-- | odb/relational/pgsql/source.cxx | 49 | ||||
-rw-r--r-- | odb/relational/processor.cxx | 1102 | ||||
-rw-r--r-- | odb/relational/schema.hxx | 6 | ||||
-rw-r--r-- | odb/relational/source.cxx | 474 | ||||
-rw-r--r-- | odb/relational/source.hxx | 114 | ||||
-rw-r--r-- | odb/relational/sqlite/common.cxx | 3 | ||||
-rw-r--r-- | odb/relational/sqlite/source.cxx | 2 | ||||
-rw-r--r-- | odb/relational/validator.cxx | 296 |
18 files changed, 1123 insertions, 1840 deletions
diff --git a/odb/relational/common.cxx b/odb/relational/common.cxx index 3916184..e9b3485 100644 --- a/odb/relational/common.cxx +++ b/odb/relational/common.cxx @@ -88,8 +88,8 @@ namespace relational { string const& fq_name (class_fq_name (c)); string guard ( - make_guard ( - "ODB_ALIAS_TRAITS_" + alias + "_FOR_" + flat_name (fq_name))); + make_guard ("ODB_" + string (db.string ()) + "_ALIAS_TRAITS_" + + alias + "_FOR_" + flat_name (fq_name))); if (specs_.find (guard) != specs_.end ()) return; @@ -107,19 +107,20 @@ namespace relational << "#define " << guard << endl; os << "template <bool d>" << endl - << "struct alias_traits< " << fq_name << ", " << tag << ", d >" + << "struct alias_traits< " << fq_name << ", id_" << db << ", " << + tag << ", d >" << "{" << "static const char table_name[];"; if (poly_derived) os << "typedef alias_traits< " << class_fq_name (*poly_base) << ", " << - tag << " > base_traits;"; + "id_" << db << ", " << tag << " > base_traits;"; os << "};"; os << "template <bool d>" << endl - << "const char alias_traits< " << fq_name << ", " << tag << - ", d >::" << endl + << "const char alias_traits< " << fq_name << ", id_" << db << ", " << + tag << ", d >::" << endl << "table_name[] = "; if (poly_root != 0) @@ -146,7 +147,8 @@ namespace relational query_columns_base (semantics::class_& c) //@@ context::{cur,top}_object : decl_ (false) { - scope_ = "query_columns_base< " + class_fq_name (c) + " >"; + scope_ = "query_columns_base< " + class_fq_name (c) + ", id_" + + db.string () + " >"; } void query_columns_base:: @@ -244,7 +246,8 @@ namespace relational string const& fq_name (class_fq_name (c)); os << "typedef" << endl - << "odb::alias_traits< " << fq_name << ", " << tag << " >" << endl + << "odb::alias_traits< " << fq_name << ", id_" << db << ", " << + tag << " >" << endl << name << "_alias_;" << endl; @@ -254,6 +257,7 @@ namespace relational << "odb::query_pointer<" << endl << " odb::pointer_query_columns<" << endl << " " << fq_name << "," << endl + << " id_" << db << "," << endl << " " << name << "_alias_ > >" << endl << name << "_type_ ;" << endl @@ -284,7 +288,7 @@ namespace relational : ptr_ (ptr), decl_ (false), in_ptr_ (false) { scope_ = ptr ? "pointer_query_columns" : "query_columns"; - scope_ += "< " + class_fq_name (c) + ", A >"; + scope_ += "< " + class_fq_name (c) + ", id_" + db.string () + ", A >"; } void query_columns:: @@ -474,6 +478,7 @@ namespace relational << "odb::query_pointer<" << endl << " odb::pointer_query_columns<" << endl << " " << class_fq_name (c) << "," << endl + << " id_" << db << "," << endl << " " << name << "_alias_ > >" << endl << name << "_pointer_type_;" << endl; @@ -519,6 +524,7 @@ namespace relational << "odb::query_pointer<" << endl << " odb::pointer_query_columns<" << endl << " " << class_fq_name (c) << "," << endl + << " id_" << db << "," << endl << " " << name << "_alias_ > >" << endl << name << "_pointer_type_;" << endl; diff --git a/odb/relational/common.hxx b/odb/relational/common.hxx index 26e8197..b951d15 100644 --- a/odb/relational/common.hxx +++ b/odb/relational/common.hxx @@ -336,7 +336,7 @@ namespace relational static B* create (B const& prototype) { - database db (context::current ().options.database ()); + database db (context::current ().options.database ()[0]); if (map_ != 0) { diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx index 538962b..1295106 100644 --- a/odb/relational/header.cxx +++ b/odb/relational/header.cxx @@ -13,15 +13,14 @@ traverse_object (type& c) using semantics::data_member; data_member* id (id_member (c)); - bool auto_id (id ? id->count ("auto") : false); - bool base_id (id ? &id->scope () != &c : false); // Comes from base. + bool auto_id (id && auto_ (*id)); + bool base_id (id && &id->scope () != &c); // Comes from base. data_member* optimistic (context::optimistic (c)); type* poly_root (polymorphic (c)); bool poly (poly_root != 0); bool poly_derived (poly && poly_root != &c); - type* poly_base (poly_derived ? &polymorphic_base (c) : 0); data_member* discriminator (poly ? context::discriminator (*poly_root) : 0); bool abst (abstract (c)); @@ -33,14 +32,6 @@ traverse_object (type& c) os << "// " << class_name (c) << 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 ()) @@ -58,59 +49,38 @@ traverse_object (type& c) pointer_query_columns_type_->traverse (c); } - // object_traits + // object_traits_impl // os << "template <>" << endl - << "class access::object_traits< " << type << " >" + << "class access::object_traits_impl< " << type << ", id_" << db << + " >:" << endl + << " public access::object_traits< " << type << " >" << "{" << "public:" << endl; object_public_extra_pre (c); - // object_type & pointer_type - // - os << "typedef " << type << " object_type;" - << "typedef " << c.get<string> ("object-pointer") << " pointer_type;" - << "typedef odb::pointer_traits<pointer_type> pointer_traits;" - << endl; - - // polymorphic, root_type, base_type, etc. + // Polymorphic root_traits, base_traits, and discriminator_image_type. // - os << "static const bool polymorphic = " << (poly ? "true" : "false") << ";"; - if (poly) { - os << "typedef " << class_fq_name (*poly_root) << " root_type;" - << "typedef object_traits<root_type> root_traits;"; + if (!abst) + os << "typedef polymorphic_entry<object_type, id_" << db << + "> entry_type;"; + + os << "typedef object_traits_impl<root_type, id_" << db << "> " << + "root_traits;"; if (poly_derived) { - os << "typedef " << class_fq_name (*poly_base) << " base_type;" - << "typedef object_traits<base_type> base_traits;" - << "typedef root_traits::discriminator_type discriminator_type;" - << "typedef odb::polymorphic_concrete_info<root_type> info_type;"; - - if (abst) - os << "typedef odb::polymorphic_abstract_info<root_type> " << - "abstract_info_type;"; - else - os << "typedef odb::polymorphic_entry<object_type> entry_type;"; - - // Calculate our hierarchy depth (number of classes). - // - size_t depth (polymorphic_depth (c)); - - os << "static const std::size_t depth = " << depth << "UL;"; + os << "typedef object_traits_impl<base_type, id_" << db << "> " << + "base_traits;" + << endl; } else { - semantics::names* hint; - semantics::type& t (utype (*discriminator, hint)); - - os << "typedef " << t.fq_name (hint) << " discriminator_type;" - << endl; - - os << "struct discriminator_image_type" + os << endl + << "struct discriminator_image_type" << "{"; discriminator_image_member_->traverse (*discriminator); @@ -120,23 +90,10 @@ traverse_object (type& c) os << "std::size_t version;" << "};"; - - os << "typedef odb::polymorphic_map<object_type> map_type;" - << "typedef odb::polymorphic_concrete_info<object_type> info_type;"; - - if (abst) - os << "typedef odb::polymorphic_abstract_info<object_type> " << - "abstract_info_type;"; - else - os << "typedef odb::polymorphic_entry<object_type> entry_type;"; - - os << "static const std::size_t depth = 1UL;"; } } - os << endl; - - // id_type & id_image_type + // id_image_type // if (id != 0) { @@ -144,44 +101,14 @@ traverse_object (type& c) { semantics::class_& b ( dynamic_cast<semantics::class_&> (id->scope ())); - string const& type (class_fq_name (b)); + string const& type (); - os << "typedef object_traits< " << type << " >::id_type id_type;"; - - if (optimistic != 0) - os << "typedef object_traits< " << type << " >::version_type " << - "version_type;"; - - if (poly_derived) - os << "typedef object_traits< " << type << " >:: id_image_type " << - "id_image_type;" - << "static const bool auto_id = false;" - << endl; - else - os << "typedef object_traits< " << type << " >::id_image_type " << - "id_image_type;" - << "static const bool auto_id = object_traits< " << type << - " >::auto_id;" - << endl; + os << "typedef object_traits_impl< " << class_fq_name (b) << ", " << + "id_" << db << " >::id_image_type id_image_type;" + << endl; } else { - { - semantics::names* hint; - semantics::type& t (utype (*id, hint)); - os << "typedef " << t.fq_name (hint) << " id_type;"; - } - - if (optimistic != 0) - { - semantics::names* hint; - semantics::type& t (utype (*optimistic, hint)); - os << "typedef " << t.fq_name (hint) << " version_type;"; - } - - os << "static const bool auto_id = " << (auto_id ? "true;" : "false;") - << endl; - os << "struct id_image_type" << "{"; @@ -194,19 +121,6 @@ traverse_object (type& c) << "};"; } } - else if (!reuse_abst) - { - // Object without id. - // - os << "typedef void id_type;" - << "static const bool auto_id = false;" - << endl; - } - - // abstract - // - os << "static const bool abstract = " << (abst ? "true" : "false") << ";" - << endl; // Polymorphic map. // @@ -236,19 +150,9 @@ traverse_object (type& c) // Functions (abstract and concrete). // - // id () - // if (id != 0 || !reuse_abst) - { - // We want to generate a dummy void id() accessor even if this - // object has no id to help us in the runtime. This way we can - // write generic code that will work for both void and non-void - // ids. - // - os << "static id_type" << endl - << "id (const object_type&);" + os << "using object_traits<object_type>::id;" << endl; - } if (!poly_derived && id != 0) { @@ -370,45 +274,6 @@ traverse_object (type& c) return; } - // Cache traits typedefs. - // - if (id == 0) - { - os << "typedef" << endl - << "odb::no_id_pointer_cache_traits<pointer_type>" << endl - << "pointer_cache_traits;" - << "typedef" << endl - << "odb::no_id_reference_cache_traits<object_type>" << endl - << "reference_cache_traits;" - << endl; - } - else - { - char const* p (session (c) ? "" : "no_op_"); - - if (poly_derived) - { - os << "typedef" << endl - << "odb::" << p << "pointer_cache_traits<" << - "root_traits::pointer_type>" << endl - << "pointer_cache_traits;" - << "typedef" << endl - << "odb::" << p << "reference_cache_traits<root_type>" << endl - << "reference_cache_traits;" - << endl; - } - else - { - os << "typedef" << endl - << "odb::" << p << "pointer_cache_traits<pointer_type>" << endl - << "pointer_cache_traits;" - << "typedef" << endl - << "odb::" << p << "reference_cache_traits<object_type>" << endl - << "reference_cache_traits;" - << endl; - } - } - // Statements typedefs. // if (poly) @@ -418,6 +283,7 @@ traverse_object (type& c) << db << "::polymorphic_derived_object_statements" << "<object_type>" << endl << "statements_type;" + << endl << "typedef" << endl << db << "::polymorphic_root_object_statements<root_type>" << endl << "root_statements_type;" @@ -426,6 +292,7 @@ traverse_object (type& c) os << "typedef" << endl << db << "::polymorphic_root_object_statements<object_type>" << endl << "statements_type;" + << endl << "typedef statements_type root_statements_type;" << "typedef " << db << "::object_statements<object_type> " << "base_statements_type;" @@ -451,7 +318,7 @@ traverse_object (type& c) { // query_base_type // - os << "typedef " << db << "::query query_base_type;" + os << "typedef " << db << "::query_base query_base_type;" << endl; } @@ -526,16 +393,6 @@ traverse_object (type& c) // Functions (concrete). // - // callback () - // - os << "static void" << endl - << "callback (database&, object_type&, callback_event);" - << endl; - - os << "static void" << endl - << "callback (database&, const object_type&, callback_event);" - << endl; - // persist () // os << "static void" << endl @@ -622,13 +479,27 @@ traverse_object (type& c) // if (options.generate_query ()) { - os << "static result<object_type>" << endl - << "query (database&, const query_base_type&);" - << endl; + if (!options.omit_unprepared ()) + { + os << "static result<object_type>" << endl + << "query (database&, const query_base_type&);" + << endl; + } os << "static unsigned long long" << endl << "erase_query (database&, const query_base_type&);" << 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; + + os << "static odb::details::shared_ptr<result_impl>" << endl + << "execute_query (prepared_query_impl&);" + << endl; + } } // create_schema () @@ -736,6 +607,224 @@ traverse_object (type& c) } os << "};"; + + + // object_traits_impl< , id_default> + // + // Note that it is not generated for reuse-abstract classes. + // + if (options.default_database_specified () && + options.default_database () == db) + { + os << "template <>" << endl + << "class access::object_traits_impl< " << type << ", " << + "id_default >:" << endl + << " public access::object_traits_impl< " << type << ", " << + "id_" << db << " >" + << "{" + << "};"; + } +} + +void relational::header::class1:: +traverse_view (type& c) +{ + string const& type (class_fq_name (c)); + + os << "// " << class_name (c) << endl + << "//" << endl; + + // view_traits_impl + // + os << "template <>" << endl + << "class access::view_traits_impl< " << type << ", id_" << + db << " >:" << endl + << " public access::view_traits< " << type << " >" + << "{" + << "public:" << endl; + + view_public_extra_pre (c); + + // image_type + // + image_type_->traverse (c); + + os << "typedef " << db << "::view_statements<view_type> statements_type;" + << endl; + + // + // Query. + // + + // query_base_type and query_columns (definition generated by class2). + // + os << "typedef " << db << "::query_base query_base_type;" + << "struct query_columns"; + + if (c.get<size_t> ("object-count") == 0) + os << "{" + << "};"; + else + os << ";" + << endl; + + // + // Functions. + // + + // grow () + // + if (generate_grow) + { + os << "static bool" << endl + << "grow (image_type&, " << truncated_vector << ");" + << endl; + } + + // bind (image_type) + // + os << "static void" << endl + << "bind (" << bind_vector << ", image_type&);" + << endl; + + // init (view, image) + // + os << "static void" << endl + << "init (view_type&, const image_type&, database*);" + << endl; + + // column_count + // + os << "static const std::size_t column_count = " << + column_count (c).total << "UL;" + << endl; + + // Statements. + // + view_query& vq (c.get<view_query> ("query")); + + if (vq.kind != view_query::runtime) + { + os << "static query_base_type" << endl + << "query_statement (const query_base_type&);" + << endl; + } + + // + // Functions. + // + + // query () + // + if (!options.omit_unprepared ()) + os << "static result<view_type>" << endl + << "query (database&, const query_base_type&);" + << 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; + + os << "static odb::details::shared_ptr<result_impl>" << endl + << "execute_query (prepared_query_impl&);" + << endl; + } + + view_public_extra_post (c); + + os << "};"; + + // view_traits_impl< , id_default> + // + if (options.default_database_specified () && + options.default_database () == db) + { + os << "template <>" << endl + << "class access::view_traits_impl< " << type << ", " << + "id_default >:" << endl + << " public access::view_traits_impl< " << type << ", " << + "id_" << db << " >" + << "{" + << "};"; + } +} + +void relational::header::class1:: +traverse_composite (type& c) +{ + string const& type (class_fq_name (c)); + + os << "// " << class_name (c) << endl + << "//" << endl; + + os << "template <>" << endl + << "class access::composite_value_traits< " << type << ", " << + "id_" << db << " >" + << "{" + << "public:" << endl; + + // value_type + // + os << "typedef " << type << " value_type;" + << endl; + + // image_type + // + image_type_->traverse (c); + + // Containers. + // + { + instance<container_traits> t (c); + t->traverse (c); + } + + // grow () + // + if (generate_grow) + { + os << "static bool" << endl + << "grow (image_type&, " << truncated_vector << ");" + << endl; + } + + // bind (image_type) + // + os << "static void" << endl + << "bind (" << bind_vector << ", image_type&, " << + db << "::statement_kind);" + << endl; + + // init (image, value) + // + os << "static " << (generate_grow ? "bool" : "void") << endl + << "init (image_type&, const value_type&, " << db << "::statement_kind);" + << endl; + + // init (value, image) + // + os << "static void" << endl + << "init (value_type&, const image_type&, database*);" + << endl; + + if (!has_a (c, test_container)) + { + // get_null (image) + // + os << "static bool" << endl + << "get_null (const image_type&);" + << endl; + + // set_null (image) + // + os << "static void" << endl + << "set_null (image_type&, " << db << "::statement_kind);" + << endl; + } + + os << "};"; } void relational::header:: diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index 25f9480..c0e1e89 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -64,9 +64,11 @@ namespace relational string const& type (class_fq_name (c)); if (obj) - os << "object_traits< " << type << " >::image_type"; + os << "object_traits_impl< " << type << ", id_" << db << + " >::image_type"; else - os << "composite_value_traits< " << type << " >::image_type"; + os << "composite_value_traits< " << type << ", id_" << db << + " >::image_type"; } private: @@ -117,7 +119,7 @@ namespace relational os << "{"; if (poly_derived) - os << "object_traits<base_type>::image_type* base;" + os << "base_traits::image_type* base;" << endl; names (c); @@ -173,7 +175,7 @@ namespace relational } os << (ptr_ ? "pointer_query_columns" : "query_columns") << "< " << - class_fq_name (c) << ", "; + class_fq_name (c) << ", id_" << db << ", "; // If our base is polymorphic, then it has its own table/alias. // @@ -213,7 +215,7 @@ namespace relational << "//" << endl << "typedef " << (ptr_ ? "pointer_query_columns" : "query_columns") << "< " << - class_fq_name (c) << ", "; + class_fq_name (c) << ", id_" << db << ", "; if (polymorphic (c)) os << "typename A::base_traits"; @@ -246,7 +248,8 @@ namespace relational if (ptr_) { os << "template <typename A>" << endl - << "struct pointer_query_columns< " << type << ", A >"; + << "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. @@ -254,7 +257,7 @@ namespace relational if (!has_a (c, test_pointer | include_base)) { os << ":" << endl - << " query_columns< " << type << ", A >" + << " query_columns< " << type << ", id_" << db << ", A >" << "{" << "};"; } @@ -298,7 +301,8 @@ namespace relational // table alias (A) template argument. // os << "template <>" << endl - << "struct query_columns_base< " << type << " >" + << "struct query_columns_base< " << type << ", id_" << + db << " >" << "{"; instance<query_columns_base> t; @@ -308,11 +312,11 @@ namespace relational } os << "template <typename A>" << endl - << "struct query_columns< " << type << ", A >"; + << "struct query_columns< " << type << ", id_" << db << ", A >"; if (has_ptr) os << ":" << endl - << " query_columns_base< " << type << " >"; + << " query_columns_base< " << type << ", id_" << db << " >"; { instance<query_columns_bases> b (ptr_, !has_ptr); @@ -540,10 +544,11 @@ namespace relational string const& type (class_fq_name (b)); if (object (b)) - os << ": access::object_traits< " << type << " >::" << name; + os << ": access::object_traits_impl< " << type << ", id_" << + db << " >::" << name; else - os << ": access::composite_value_traits< " << type << " >::" << - public_name (m) << "_traits"; // No prefix_. + os << ": access::composite_value_traits< " << type << ", id_" << + db << " >::" << public_name (m) << "_traits"; // No prefix_. } os << "{"; @@ -992,7 +997,7 @@ namespace relational } virtual void - traverse_object (type& c); + traverse_object (type&); virtual void view_public_extra_pre (type&) @@ -1005,196 +1010,10 @@ namespace relational } virtual void - traverse_view (type& c) - { - string const& type (class_fq_name (c)); - - os << "// " << class_name (c) << endl - << "//" << endl; - - os << "template <>" << endl - << "struct class_traits< " << type << " >" - << "{" - << "static const class_kind kind = class_view;" - << "};"; - - os << "template <>" << endl - << "class access::view_traits< " << type << " >" - << "{" - << "public:" << endl; - - view_public_extra_pre (c); - - // view_type & pointer_type - // - os << "typedef " << type << " view_type;" - << "typedef " << c.get<string> ("object-pointer") << " pointer_type;" - << endl; - - // image_type - // - image_type_->traverse (c); - - // - // Query. - // - - // query_base_type and query_columns (definition generated by class2). - // - os << "typedef " << db << "::query query_base_type;" - << "struct query_columns"; - - if (c.get<size_t> ("object-count") == 0) - os << "{" - << "};"; - else - os << ";" - << endl; - - // - // Functions. - // - - // grow () - // - if (generate_grow) - { - os << "static bool" << endl - << "grow (image_type&, " << truncated_vector << ");" - << endl; - } - - // bind (image_type) - // - os << "static void" << endl - << "bind (" << bind_vector << ", image_type&);" - << endl; - - // init (view, image) - // - os << "static void" << endl - << "init (view_type&, const image_type&, database*);" - << endl; - - // column_count - // - os << "static const std::size_t column_count = " << - column_count (c).total << "UL;" - << endl; - - // Statements. - // - view_query& vq (c.get<view_query> ("query")); - - if (vq.kind != view_query::runtime) - { - os << "static query_base_type" << endl - << "query_statement (const query_base_type&);" - << endl; - } - - // - // Functions. - // - - // callback () - // - os << "static void" << endl - << "callback (database&, view_type&, callback_event);" - << endl; - - // query () - // - os << "static result<view_type>" << endl - << "query (database&, const query_base_type&);" - << endl; - - view_public_extra_post (c); - - os << "};"; - } + traverse_view (type&); virtual void - traverse_composite (type& c) - { - string const& type (class_fq_name (c)); - - os << "// " << class_name (c) << endl - << "//" << endl; - - os << "template <>" << endl - << "struct class_traits< " << type << " >" - << "{" - << "static const class_kind kind = class_composite;" - << "};"; - - os << "template <>" << endl - << "class access::composite_value_traits< " << type << " >" - << "{" - << "public:" << endl; - - // value_type - // - os << "typedef " << type << " value_type;" - << endl; - - // image_type - // - image_type_->traverse (c); - - // Containers. - // - { - instance<container_traits> t (c); - t->traverse (c); - } - - // grow () - // - if (generate_grow) - { - os << "static bool" << endl - << "grow (image_type&, " << truncated_vector << ");" - << endl; - } - - // bind (image_type) - // - os << "static void" << endl - << "bind (" << bind_vector << ", image_type&, " << - db << "::statement_kind);" - << endl; - - // init (image, value) - // - os << "static " << (generate_grow ? "bool" : "void") << endl - << "init (image_type&, const value_type&, " << - db << "::statement_kind);" - << endl; - - // init (value, image) - // - os << "static void" << endl - << "init (value_type&, const image_type&, database*);" - << endl; - - if (!has_a (c, test_container)) - { - // get_null (image) - // - os << "static bool" << endl - << "get_null (const image_type&);" - << endl; - - // set_null (image) - // - os << "static void" << endl - << "set_null (image_type&, " << db << "::statement_kind);" - << endl; - } - - os << "};"; - } + traverse_composite (type&); private: instance<image_type> image_type_; @@ -1306,7 +1125,8 @@ namespace relational } } - os << "struct access::view_traits< " << type << " >::query_columns"; + os << "struct access::view_traits_impl< " << type << ", id_" << + db << " >::query_columns"; if (obj_count > 1) { @@ -1329,19 +1149,20 @@ namespace relational << "//" << endl << "typedef" << endl << "odb::pointer_query_columns<" << endl - << " " << otype << "," << endl; + << " " << otype << "," << endl + << " id_" << db << "," << endl; if (alias && (polymorphic (o) || table.qualified () || i->alias != table.uname ())) { string tag (escape (i->alias + "_alias_tag")); - os << " odb::alias_traits< " << otype << ", " << - tag << " > >" << endl; + os << " odb::alias_traits< " << otype << ", id_" << db << + ", " << tag << " > >" << endl; } else - os << " odb::access::object_traits< " << otype << - " > >" << endl; + os << " odb::access::object_traits_impl< " << otype << + ", id_" << db << " > >" << endl; os << oname << ";" << endl; @@ -1370,18 +1191,20 @@ namespace relational os << ":" << endl << " odb::pointer_query_columns<" << endl - << " " << otype << "," << endl; + << " " << otype << "," << endl + << " id_" << db << "," << endl; if (alias && (polymorphic (o) || table.qualified () || vo->alias != table.uname ())) { string tag (escape (vo->alias + "_alias_tag")); - os << " odb::alias_traits< " << otype << ", " << - tag << " > >"; + os << " odb::alias_traits< " << otype << ", id_" << + db << ", " << tag << " > >"; } else - os << " odb::access::object_traits< " << otype << " > >"; + os << " odb::access::object_traits_impl< " << otype << + ", id_" << db << " > >"; os << "{" << "};"; @@ -1410,9 +1233,12 @@ namespace relational virtual void generate () { - os << "#include <odb/details/buffer.hxx>" << endl - << "#include <odb/details/unused.hxx>" << endl - << endl; + os << "#include <odb/details/buffer.hxx>" << endl; + + if (options.generate_query ()) + os << "#include <odb/details/shared-ptr.hxx>" << endl; + + os << endl; os << "#include <odb/" << db << "/version.hxx>" << endl << "#include <odb/" << db << "/forward.hxx>" << endl diff --git a/odb/relational/inline.hxx b/odb/relational/inline.hxx index 76c29f1..466e348 100644 --- a/odb/relational/inline.hxx +++ b/odb/relational/inline.hxx @@ -14,68 +14,6 @@ namespace relational namespace inline_ { // - // - struct callback_calls: traversal::class_, virtual context - { - typedef callback_calls base; - - callback_calls () - { - *this >> inherits_ >> *this; - } - - callback_calls (callback_calls const&) - : root_context (), //@@ -Wextra - context () - { - *this >> inherits_ >> *this; - } - - virtual void - traverse (type& c, bool constant) - { - const_ = constant; - traverse (c); - } - - virtual void - traverse (type& c) - { - bool obj (object (c)); - - // Ignore transient bases. - // - if (!(obj || view (c))) - return; - - if (c.count ("callback")) - { - string name (c.get<string> ("callback")); - - // In case of the const instance, we only generate the call if - // there is a const callback. - // - string const& type (class_fq_name (c)); - - if (const_) - { - if (c.count ("callback-const")) - os << "static_cast< const " << type << "& > (x)." << - name << " (e, db);"; - } - else - os << "static_cast< " << type << "& > (x)." << name << " (e, db);"; - } - else if (obj) - inherits (c); - } - - protected: - bool const_; - traversal::inherits inherits_; - }; - - // // get/set null (composite value only) // @@ -121,7 +59,8 @@ namespace relational virtual void traverse_composite (member_info& mi) { - string traits ("composite_value_traits< " + mi.fq_type () + " >"); + string traits ("composite_value_traits< " + mi.fq_type () + ", id_" + + db.string () + " >"); if (get_) os << "r = r && " << traits << "::get_null (" << @@ -145,7 +84,8 @@ namespace relational if (!composite (c)) return; - string traits ("composite_value_traits< " + class_fq_name (c) + " >"); + string traits ("composite_value_traits< " + class_fq_name (c) + + ", id_" + db.string () + " >"); // If the derived value type is readonly, then set will never be // called with sk == statement_update. @@ -209,7 +149,7 @@ namespace relational if (object (c)) traverse_object (c); - if (view (c)) + else if (view (c)) traverse_view (c); else if (composite (c)) traverse_composite (c); @@ -226,11 +166,11 @@ namespace relational traverse_object (type& c) { semantics::data_member* id (id_member (c)); - bool base_id (id ? &id->scope () != &c : false); // Comes from base. + bool base_id (id && &id->scope () != &c); // Comes from base. semantics::data_member* optimistic (context::optimistic (c)); - // Base class the contains the object id and version for optimistic + // Base class that contains the object id and version for optimistic // concurrency. // type* base ( @@ -244,7 +184,8 @@ namespace relational bool reuse_abst (abst && !poly); string const& type (class_fq_name (c)); - string traits ("access::object_traits< " + type + " >"); + string traits ("access::object_traits_impl< " + type + ", id_" + + db.string () + " >"); os << "// " << class_name (c) << endl << "//" << endl @@ -252,39 +193,6 @@ namespace relational object_extra (c); - // id (object_type) - // - if (id != 0 || !reuse_abst) - { - os << "inline" << endl - << traits << "::id_type" << endl - << traits << "::" << endl - << "id (const object_type&" << (id != 0 ? " o" : "") << ")" - << "{"; - - if (id != 0) - { - if (base_id) - os << "return object_traits< " << class_fq_name (*base) << - " >::id (o);"; - else - { - // Get the id using the accessor expression. If this is not - // a synthesized expression, then output its location for - // easier error tracking. - // - member_access& ma (id->get<member_access> ("get")); - - if (!ma.synthesized) - os << "// From " << location_string (ma.loc, true) << endl; - - os << "return " << ma.translate ("o") << ";"; - } - } - - os << "}"; - } - if (id != 0 && base_id) { if (!poly_derived) @@ -298,8 +206,8 @@ namespace relational << traits << "::" << endl << "id (const image_type& i)" << "{" - << "return object_traits< " << class_fq_name (*base) << - " >::id (i);" + << "return object_traits_impl< " << class_fq_name (*base) << + ", id_" << db << " >::id (i);" << "}"; } @@ -312,8 +220,8 @@ namespace relational << traits << "::" << endl << "version (const image_type& i)" << "{" - << "return object_traits< " << class_fq_name (*base) << - " >::version (i);" + << "return object_traits_impl< " << class_fq_name (*base) << + ", id_" << db << " >::version (i);" << "}"; } } @@ -325,8 +233,8 @@ namespace relational << "bind (" << bind_vector << " b, id_image_type& i" << (optimistic != 0 ? ", bool bv" : "") << ")" << "{" - << "object_traits< " << class_fq_name (*base) << - " >::bind (b, i" << (optimistic != 0 ? ", bv" : "") << ");" + << "object_traits_impl< " << class_fq_name (*base) << ", id_" << + db << " >::bind (b, i" << (optimistic != 0 ? ", bv" : "") << ");" << "}"; os << "inline" << endl @@ -334,8 +242,8 @@ namespace relational << "init (id_image_type& i, const id_type& id" << (optimistic != 0 ? ", const version_type* v" : "") << ")" << "{" - << "object_traits< " << class_fq_name (*base) << - " >::init (i, id" << (optimistic != 0 ? ", v" : "") << ");" + << "object_traits_impl< " << class_fq_name (*base) << ", id_" << + db << " >::init (i, id" << (optimistic != 0 ? ", v" : "") << ");" << "}"; } @@ -390,7 +298,6 @@ namespace relational os << "}"; } - // // The rest does not apply to reuse-abstract objects. // if (reuse_abst) @@ -410,31 +317,6 @@ namespace relational << "}"; } - // callback () - // - os << "inline" << endl - << "void " << traits << "::" << endl - << "callback (database& db, object_type& x, callback_event e)" - << endl - << "{" - << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (x);" - << "ODB_POTENTIALLY_UNUSED (e);" - << endl; - callback_calls_->traverse (c, false); - os << "}"; - - os << "inline" << endl - << "void " << traits << "::" << endl - << "callback (database& db, const object_type& x, callback_event e)" - << "{" - << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (x);" - << "ODB_POTENTIALLY_UNUSED (e);" - << endl; - callback_calls_->traverse (c, true); - os << "}"; - // load_() // if (id != 0 && !(poly_derived || has_a (c, test_container))) @@ -464,7 +346,7 @@ namespace relational << "{"; if (poly_derived) - os << "return object_traits<base_type>::root_image (*i.base);"; + os << "return base_traits::root_image (*i.base);"; else os << "return i;"; @@ -479,9 +361,7 @@ namespace relational << "{"; if (poly_derived) - os << "typedef object_traits<base_type> base_traits;" - << endl - << "details::unique_ptr<base_traits::image_type> p (" << endl + os << "details::unique_ptr<base_traits::image_type> p (" << endl << "base_traits::clone_image (*i.base));" << "image_type* c (new image_type (i));" << "c->base = p.release ();" @@ -499,9 +379,7 @@ namespace relational << "{"; if (poly_derived) - os << "typedef object_traits<base_type> base_traits;" - << endl - << "base_traits::image_type* b (d.base);" + os << "base_traits::image_type* b (d.base);" << "base_traits::copy_image (*b, *s.base);" << "d = s;" // Overwrites the base pointer. << "d.base = b;"; @@ -518,7 +396,7 @@ namespace relational << "{"; if (poly_derived) - os << "object_traits<base_type>::free_image (i->base);"; + os << "base_traits::free_image (i->base);"; os << "delete i;" << "}"; @@ -534,34 +412,22 @@ namespace relational traverse_view (type& c) { string const& type (class_fq_name (c)); - string traits ("access::view_traits< " + type + " >"); + string traits ("access::view_traits_impl< " + type + ", id_" + + db.string () + " >"); os << "// " << class_name (c) << endl << "//" << endl << endl; view_extra (c); - - // callback () - // - os << "inline" << endl - << "void " << traits << "::" << endl - << "callback (database& db, view_type& x, callback_event e)" - << endl - << "{" - << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (x);" - << "ODB_POTENTIALLY_UNUSED (e);" - << endl; - callback_calls_->traverse (c, false); - os << "}"; } virtual void traverse_composite (type& c) { string const& type (class_fq_name (c)); - string traits ("access::composite_value_traits< " + type + " >"); + string traits ("access::composite_value_traits< " + type + ", id_" + + db.string () + " >"); os << "// " << class_name (c) << endl << "//" << endl @@ -602,8 +468,6 @@ namespace relational } private: - instance<callback_calls> callback_calls_; - instance<null_base> get_null_base_; traversal::inherits get_null_base_inherits_; instance<null_member> get_null_member_; diff --git a/odb/relational/mssql/common.cxx b/odb/relational/mssql/common.cxx index b2f982a..d802e54 100644 --- a/odb/relational/mssql/common.cxx +++ b/odb/relational/mssql/common.cxx @@ -202,7 +202,8 @@ namespace relational void member_image_type:: traverse_composite (member_info& mi) { - type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type"; + type_ = "composite_value_traits< " + mi.fq_type () + + ", id_mssql >::image_type"; } void member_image_type:: diff --git a/odb/relational/mysql/common.cxx b/odb/relational/mysql/common.cxx index b8fa4c3..9d62b6b 100644 --- a/odb/relational/mysql/common.cxx +++ b/odb/relational/mysql/common.cxx @@ -168,7 +168,8 @@ namespace relational void member_image_type:: traverse_composite (member_info& mi) { - type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type"; + type_ = "composite_value_traits< " + mi.fq_type () + + ", id_mysql >::image_type"; } void member_image_type:: diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx index 494abf5..48ae1f2 100644 --- a/odb/relational/mysql/source.cxx +++ b/odb/relational/mysql/source.cxx @@ -346,7 +346,7 @@ namespace relational traverse_composite (member_info& mi) { os << "if (composite_value_traits< " << mi.fq_type () << - " >::grow (" << endl + ", id_mysql >::grow (" << endl << "i." << mi.var << "value, t + " << index_ << "UL))" << "{" << "grew = true;" diff --git a/odb/relational/oracle/common.cxx b/odb/relational/oracle/common.cxx index e9d8390..04bb0f8 100644 --- a/odb/relational/oracle/common.cxx +++ b/odb/relational/oracle/common.cxx @@ -188,7 +188,8 @@ namespace relational void member_image_type:: traverse_composite (member_info& mi) { - type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type"; + type_ = "composite_value_traits< " + mi.fq_type () + + ", id_oracle >::image_type"; } void member_image_type:: diff --git a/odb/relational/pgsql/common.cxx b/odb/relational/pgsql/common.cxx index 3d7e01e..811269e 100644 --- a/odb/relational/pgsql/common.cxx +++ b/odb/relational/pgsql/common.cxx @@ -144,7 +144,8 @@ namespace relational void member_image_type:: traverse_composite (member_info& mi) { - type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type"; + type_ = "composite_value_traits< " + mi.fq_type () + + ", id_pgsql >::image_type"; } void member_image_type:: diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index 23600d0..332e25b 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -295,7 +295,7 @@ namespace relational traverse_composite (member_info& mi) { os << "if (composite_value_traits< " << mi.fq_type () << - " >::grow (" << endl + ", id_pgsql >::grow (" << endl << "i." << mi.var << "value, t + " << index_ << "UL))" << "{" << "grew = true;" @@ -642,7 +642,7 @@ namespace relational string const& n (class_fq_name (c)); string const& fn (flat_name (n)); - string traits ("access::object_traits< " + n + " >"); + string traits ("access::object_traits_impl< " + n + ", id_pgsql >"); os << "const char " << traits << "::" << endl << "persist_statement_name[] = " << strlit (fn + "_persist") << ";" @@ -792,7 +792,7 @@ namespace relational { string const& n (class_fq_name (c)); string const& fn (flat_name (n)); - string traits ("access::view_traits< " + n + " >"); + string traits ("access::view_traits_impl< " + n + ", id_pgsql >"); os << "const char " << traits << "::" << endl << "query_statement_name[] = " << strlit (fn + "_query") << ";" @@ -800,14 +800,19 @@ namespace relational } virtual void - object_query_statement_ctor_args (type&) + object_query_statement_ctor_args (type&, string const& q, bool prep) { - os << "sts.connection ()," << endl - << "query_statement_name," << endl - << "query_statement + q.clause ()," << endl - << "q.parameter_types ()," << endl - << "q.parameter_count ()," << endl - << "q.parameters_binding ()," << endl + os << "sts.connection ()," << endl; + + if (prep) + os << "n," << endl; + else + os << "query_statement_name," << endl; + + os << "query_statement + " << q << ".clause ()," << endl + << q << ".parameter_types ()," << endl + << q << ".parameter_count ()," << endl + << q << ".parameters_binding ()," << endl << "imb"; } @@ -823,21 +828,27 @@ namespace relational } virtual void - view_query_statement_ctor_args (type&) + view_query_statement_ctor_args (type&, string const& q, bool prep) { - os << "sts.connection ()," << endl - << "query_statement_name," << endl - << "qs.clause ()," << endl - << "qs.parameter_types ()," << endl - << "qs.parameter_count ()," << endl - << "qs.parameters_binding ()," << endl + os << "sts.connection ()," << endl; + + if (prep) + os << "n," << endl; + else + os << "query_statement_name," << endl; + + os << q << ".clause ()," << endl + << q << ".parameter_types ()," << endl + << q << ".parameter_count ()," << endl + << q << ".parameters_binding ()," << endl << "imb"; } virtual void - post_query_ (type&) + post_query_ (type&, bool once_off) { - os << "st->deallocate ();"; + if (once_off) + os << "st->deallocate ();"; } }; entry<class_> class_entry_; diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index f000858..5100739 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -305,497 +305,14 @@ namespace relational throw operation_failed (); } - process_access (m, "get"); - process_access (m, "set"); - process_index (m); - } - - // - // Process member access expressions. - // - - enum found_type - { - found_none, - found_some, // Found something but keep looking for a better one. - found_best - }; - - // Check if a function is a suitable accessor for this member. - // - found_type - check_accessor (semantics::data_member& m, - tree f, - string const& n, - member_access& ma, - bool strict) - { - // Must be const. - // - if (!DECL_CONST_MEMFUNC_P (f)) - return found_none; - - // Accessor is a function with no arguments (other than 'this'). - // - if (DECL_CHAIN (DECL_ARGUMENTS (f)) != NULL_TREE) - return found_none; - - // Note that to get the return type we have to use - // TREE_TYPE(TREE_TYPE()) and not DECL_RESULT, as - // suggested in the documentation. - // - tree r (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f)))); - int tc (TREE_CODE (r)); - - // In the strict mode make sure the function returns for non-array - // types a value or a (const) reference to the member type and for - // array types a (const) pointer to element type. In the lax mode - // we just check that the return value is not void. - // - if (strict) - { - semantics::type& t (utype (m)); - semantics::array* ar (dynamic_cast<semantics::array*> (&t)); - - if (ar != 0 && tc != POINTER_TYPE) - return found_none; - - tree bt (ar != 0 || tc == REFERENCE_TYPE ? TREE_TYPE (r) : r); - tree bt_mv (TYPE_MAIN_VARIANT (bt)); - - if ((ar != 0 ? ar->base_type () : t).tree_node () != bt_mv) - return found_none; - } - else if (r == void_type_node) - return found_none; - - cxx_tokens& e (ma.expr); - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - e.push_back (cxx_token (0, CPP_OPEN_PAREN, n)); - e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n)); - - // See if it returns by value. - // - ma.by_value = (tc != REFERENCE_TYPE && tc != POINTER_TYPE); - - return found_best; - } - - // Check if a function is a suitable modifier for this member. - // - found_type - check_modifier (semantics::data_member& m, - tree f, - string const& n, - member_access& ma, - bool strict) - { - tree a (DECL_ARGUMENTS (f)); - a = DECL_CHAIN (a); // Skip this. - - // For a modifier, it can either be a function that returns a non- - // const reference (or non-const pointer, in case the member is an - // array) or a by-value modifier that sets a new value. If both are - // available, we prefer the former for efficiency. - // - cxx_tokens& e (ma.expr); - semantics::type& t (utype (m)); - semantics::array* ar (dynamic_cast<semantics::array*> (&t)); - - if (a == NULL_TREE) + if (m.count ("polymorphic-ref")) { - // Note that to get the return type we have to use - // TREE_TYPE(TREE_TYPE()) and not DECL_RESULT, as - // suggested in the documentation. - // - tree r (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f)))); - int tc (TREE_CODE (r)); - - // By-reference modifier. Should return a reference or a pointer. - // - if (tc != (ar != 0 ? POINTER_TYPE : REFERENCE_TYPE)) - return found_none; - - // The base type should not be const and, in strict mode, should - // match the member type. - // - tree bt (TREE_TYPE (r)); - - if (CP_TYPE_CONST_P (bt)) - return found_none; - - tree bt_mv (TYPE_MAIN_VARIANT (bt)); - - if (strict && (ar != 0 ? ar->base_type () : t).tree_node () != bt_mv) - return found_none; - - e.clear (); // Could contain by value modifier. - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - e.push_back (cxx_token (0, CPP_OPEN_PAREN, n)); - e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n)); - - return found_best; + m.set ("not-null", true); + m.set ("deferred", false); + m.set ("on-delete", sema_rel::foreign_key::cascade); } - // Otherwise look for a by value modifier, which is a function - // with a single argument. - // - else if (DECL_CHAIN (a) == NULL_TREE) - { - // In the lax mode any function with a single argument works - // for us. And we don't care what it returns. - // - if (strict) - { - // In the strict mode make sure the argument matches the - // member. This is exactly the same logic as in accessor - // with regards to arrays, references, etc. - // - tree at (TREE_TYPE (a)); - int tc (TREE_CODE (at)); - - if (ar != 0 && tc != POINTER_TYPE) - return found_none; - - tree bt (ar != 0 || tc == REFERENCE_TYPE ? TREE_TYPE (at) : at); - tree bt_mv (TYPE_MAIN_VARIANT (bt)); - - if ((ar != 0 ? ar->base_type () : t).tree_node () != bt_mv) - return found_none; - } - - if (e.empty ()) - { - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - e.push_back (cxx_token (0, CPP_OPEN_PAREN, n)); - e.push_back (cxx_token (0, CPP_QUERY)); - e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n)); - - // Continue searching in case there is version that returns a - // non-const reference which we prefer for efficiency. - // - return found_some; - } - else - return found_none; // We didn't find anything better. - } - - return found_none; - } - - void - process_access (semantics::data_member& m, std::string const& k) - { - bool virt (m.count ("virtual")); - - // Ignore certain special virtual members. - // - if (virt && (m.count ("polymorphic-ref") || m.count ("discriminator"))) - return; - - char const* kind (k == "get" ? "accessor" : "modifier"); - semantics::class_& c (dynamic_cast<semantics::class_&> (m.scope ())); - - // If we don't have an access expression, try to come up with - // one. - // - if (!m.count (k)) - { - found_type found (found_none); - semantics::access const& a (m.named ().access ()); - member_access& ma (m.set (k, member_access (m.location (), true))); - - // If this member is not virtual and is either public or if we - // are a friend of this class, then go for the member directly. - // - if (!virt && (a == semantics::access::public_ || - c.get<bool> ("friend"))) - { - ma.expr.push_back (cxx_token (0, CPP_KEYWORD, "this")); - ma.expr.push_back (cxx_token (0, CPP_DOT)); - ma.expr.push_back (cxx_token (0, CPP_NAME, m.name ())); - found = found_best; - } - - // Otherwise, try to find a suitable accessor/modifier. - // - - // First try the original name. If that doesn't produce anything, - // then try the public name. - // - bool t (k == "get" - ? options.accessor_regex_trace () - : options.modifier_regex_trace ()); - regex_mapping const& re ( - k == "get" ? accessor_regex : modifier_regex); - - for (unsigned short j (0); found != found_best && j != 2; ++j) - { - string b (j == 0 ? m.name () : public_name (m, false)); - - // Skip the second pass if original and public names are the same. - // - if (j == 1 && b == m.name ()) - continue; - - if (t) - cerr << kind << (j == 0 ? " original" : " public") - << " name '" << b << "'" << endl; - - for (regex_mapping::const_iterator i (re.begin ()); - found != found_best && i != re.end (); - ++i) - { - if (t) - cerr << "try: '" << i->regex () << "' : "; - - if (!i->match (b)) - { - if (t) - cerr << '-' << endl; - continue; - } - - string n (i->replace (b)); - - if (t) - cerr << "'" << n << "' : "; - - tree decl ( - lookup_qualified_name ( - c.tree_node (), get_identifier (n.c_str ()), false, false)); - - if (decl == error_mark_node || TREE_CODE (decl) != BASELINK) - { - if (t) - cerr << '-' << endl; - continue; - } - - // OVL_* macros work for both FUNCTION_DECL and OVERLOAD. - // - for (tree o (BASELINK_FUNCTIONS (decl)); - o != 0; - o = OVL_NEXT (o)) - { - tree f (OVL_CURRENT (o)); - - // We are only interested in public non-static member - // functions. Note that TREE_PUBLIC() returns something - // other than what we need. - // - if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (f) || - TREE_PRIVATE (f) || TREE_PROTECTED (f)) - continue; - - found_type r (k == "get" - ? check_accessor (m, f, n, ma, true) - : check_modifier (m, f, n, ma, true)); - - if (r != found_none) - { - // Update the location of the access expression to point - // to this function. - // - ma.loc = location (DECL_SOURCE_LOCATION (f)); - found = r; - } - } - - if (t) - cerr << (found != found_none ? '+' : '-') << endl; - } - } - - // If that didn't work then the generated code won't be able - // to access this member. - // - if (found == found_none) - { - location const& l (m.location ()); - - if (virt) - { - error (l) << "no suitable " << kind << " function could be " - << "automatically found for virtual data member '" - << m.name () << "'" << endl; - - info (l) << "use '#pragma db " << k << "' to explicitly " - << "specify the " << kind << " function or " - << "expression" << endl; - } - else - { - error (l) << "data member '" << m.name () << "' is " - << a.string () << " and no suitable " << kind - << " function could be automatically found" << endl; - info (l) << "consider making class 'odb::access' a friend of " - << "class '" << class_name (c) << "'" << endl; - - info (l) << "or use '#pragma db " << k << "' to explicitly " - << "specify the " << kind << " function or " - << "expression" << endl; - } - - throw operation_failed (); - } - } - - member_access& ma (m.get<member_access> (k)); - cxx_tokens& e (ma.expr); - - // If it is just a name, resolve it and convert to an appropriate - // expression. - // - if (e.size () == 1 && e.back ().type == CPP_NAME) - { - string n (e.back ().literal); - e.clear (); - - tree decl ( - lookup_qualified_name ( - c.tree_node (), get_identifier (n.c_str ()), false, false)); - - if (decl == error_mark_node) - { - error (ma.loc) << "unable to resolve data member or function " - << "name '" << n << "'" << endl; - throw operation_failed (); - } - - switch (TREE_CODE (decl)) - { - case FIELD_DECL: - { - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - break; - } - case BASELINK: - { - // OVL_* macros work for both FUNCTION_DECL and OVERLOAD. - // - for (tree o (BASELINK_FUNCTIONS (decl)); - o != 0; - o = OVL_NEXT (o)) - { - tree f (OVL_CURRENT (o)); - - // We are only interested in non-static member functions. - // - if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (f)) - continue; - - if ((k == "get" - ? check_accessor (m, f, n, ma, false) - : check_modifier (m, f, n, ma, false)) == found_best) - break; - } - - if (e.empty ()) - { - error (ma.loc) << "unable to find suitable " << kind - << " function '" << n << "'" << endl; - throw operation_failed (); - } - break; - } - default: - { - error (ma.loc) << "name '" << n << "' does not refer to a data " - << "member or function" << endl; - throw operation_failed (); - } - } - } - - // If there is no 'this' keyword, then add it as a prefix. - // - { - bool t (false); - for (cxx_tokens::iterator i (e.begin ()); i != e.end (); ++i) - { - if (i->type == CPP_KEYWORD && i->literal == "this") - { - t = true; - break; - } - } - - if (!t) - { - e.insert (e.begin (), cxx_token (0, CPP_DOT)); - e.insert (e.begin (), cxx_token (0, CPP_KEYWORD, "this")); - } - } - - // Check that there is no placeholder in the accessor expression. - // - if (k == "get" && ma.placeholder ()) - { - error (ma.loc) << "(?) placeholder in the accessor expression" - << endl; - throw operation_failed (); - } - - // Check that the member type is default-constructible if we - // have a by value modifier. - // - if (k == "set" && ma.placeholder ()) - { - semantics::class_* c (dynamic_cast<semantics::class_*> (&utype (m))); - - // Assume all other types are default-constructible. - // - if (c != 0) - { - // If this type is a class template instantiation, then make - // sure it is instantiated. While types used in real members - // will be instantiated, this is not necessarily the case for - // virtual members. Without the instantiation we won't be able - // to detect whether the type has the default ctor. - // - // It would have been cleaner to do it in post_process_pragmas() - // but there we don't yet know whether we need the default ctor. - // And it is a good idea not to require instantiability unless - // we really need it. - // - tree type (c->tree_node ()); - - if (!COMPLETE_TYPE_P (type) && - CLASSTYPE_TEMPLATE_INSTANTIATION (type)) - { - // Reset input location so that we get nice diagnostics in - // case of an error. Use the location of the virtual pragma. - // - location_t loc (m.get<location_t> ("virtual-location")); - input_location = loc; - - if (instantiate_class_template (type) == error_mark_node || - errorcount != 0 || - !COMPLETE_TYPE_P (type)) - { - error (loc) << "unable to instantiate virtual data member " << - "type" << endl; - throw operation_failed (); - } - } - - if (!c->default_ctor ()) - { - error (ma.loc) << "modifier expression requires member type " << - "to be default-constructible" << endl; - throw operation_failed (); - } - } - } + process_index (m); } // Convert index/unique specifiers to the index entry in the object. @@ -2351,44 +1868,7 @@ namespace relational struct class_: traversal::class_, context { class_ () - : std_string_ (0), std_string_hint_ (0), access_ (0) { - // Resolve the std::string type node. - // - using semantics::scope; - - for (scope::names_iterator_pair ip (unit.find ("std")); - ip.first != ip.second; ++ip.first) - { - if (scope* ns = dynamic_cast<scope*> (&ip.first->named ())) - { - scope::names_iterator_pair jp (ns->find ("string")); - - if (jp.first != jp.second) - { - std_string_ = dynamic_cast<semantics::type*> ( - &jp.first->named ()); - std_string_hint_ = &*jp.first; - break; - } - } - } - - assert (std_string_ != 0); // No std::string? - - // Resolve odb::access, if any. - // - tree odb = lookup_qualified_name ( - global_namespace, get_identifier ("odb"), false, false); - - if (odb != error_mark_node) - { - access_ = lookup_qualified_name ( - odb, get_identifier ("access"), true, false); - - access_ = (access_ != error_mark_node ? TREE_TYPE (access_) : 0); - } - *this >> member_names_ >> member_; } @@ -2400,28 +1880,12 @@ namespace relational if (k == class_other) return; - // Check if odb::access is a friend of this class. - // - c.set ("friend", access_ != 0 && is_friend (c.tree_node (), access_)); - - // Assign pointer. - // - if (k == class_object || k == class_view) - assign_pointer (c); - - // Do some additional pre-processing. - // - if (k == class_object) - traverse_object_pre (c); - names (c); - // Do some additional post-processing. - // if (k == class_object) - traverse_object_post (c); + traverse_object (c); else if (k == class_view) - traverse_view_post (c); + traverse_view (c); } // @@ -2429,149 +1893,7 @@ namespace relational // virtual void - traverse_object_pre (type& c) - { - semantics::class_* poly_root (polymorphic (c)); - - // Determine whether it is a session object. - // - if (!c.count ("session")) - { - // If this is a derived class in a polymorphic hierarchy, - // then it should have the same session value as the root. - // - if (poly_root != 0 && poly_root != &c) - c.set ("session", session (*poly_root)); - else - { - // See if any of the namespaces containing this class specify - // the session value. - // - bool found (false); - for (semantics::scope* s (&c.scope ());; s = &s->scope_ ()) - { - using semantics::namespace_; - - namespace_* ns (dynamic_cast<namespace_*> (s)); - - if (ns == 0) - continue; // Some other scope. - - if (ns->extension ()) - ns = &ns->original (); - - if (ns->count ("session")) - { - c.set ("session", ns->get<bool> ("session")); - found = true; - break; - } - - if (ns->global_scope ()) - break; - } - - // If still not found, then use the default value. - // - if (!found) - c.set ("session", options.generate_session ()); - } - } - - if (session (c)) - features.session_object = true; - - if (poly_root != 0) - { - using namespace semantics; - - semantics::data_member& idm (*id_member (*poly_root)); - - if (poly_root != &c) - { - // If we are a derived class in the polymorphic persistent - // class hierarchy, then add a synthesized virtual pointer - // member that points back to the root. - // - path const& f (idm.file ()); - size_t l (idm.line ()), col (idm.column ()); - - semantics::data_member& m ( - unit.new_node<semantics::data_member> (f, l, col, tree (0))); - m.set ("virtual", true); - - // Make it the first member in the class. - // - node_position<type, scope::names_iterator> np (c, c.names_end ()); - unit.new_edge<semantics::names> ( - np, m, idm.name (), access::public_); - - // Use the raw pointer as this member's type. - // - if (!poly_root->pointed_p ()) - { - // Create the pointer type in the graph. The pointer node - // in GCC seems to always be present, even if not explicitly - // used in the translation unit. - // - tree t (poly_root->tree_node ()); - tree ptr (TYPE_POINTER_TO (t)); - assert (ptr != 0); - ptr = TYPE_MAIN_VARIANT (ptr); - pointer& p (unit.new_node<pointer> (f, l, col, ptr)); - unit.insert (ptr, p); - unit.new_edge<points> (p, *poly_root); - assert (poly_root->pointed_p ()); - } - - unit.new_edge<belongs> (m, poly_root->pointed ().pointer ()); - - m.set ("not-null", true); - m.set ("deferred", false); - m.set ("on-delete", sema_rel::foreign_key::cascade); - - // Mark it as a special kind of id. - // - m.set ("id", true); - m.set ("polymorphic-ref", true); - } - else - { - // If we are a root of the polymorphic persistent class hierarchy, - // then add a synthesized virtual member for the discriminator. - // Use the location of the polymorphic pragma as the location of - // this member. - // - location_t loc (c.get<location_t> ("polymorphic-location")); - semantics::data_member& m ( - unit.new_node<semantics::data_member> ( - path (LOCATION_FILE (loc)), - LOCATION_LINE (loc), - LOCATION_COLUMN (loc), - tree (0))); - m.set ("virtual", true); - - // Insert it after the id member (or first if this id comes - // from reuse-base). - // - node_position<type, scope::names_iterator> np ( - c, c.find (idm.named ())); - unit.new_edge<semantics::names> ( - np, m, "typeid_", access::public_); - - belongs& edge (unit.new_edge<belongs> (m, *std_string_)); - edge.hint (*std_string_hint_); - - m.set ("readonly", true); - m.set ("discriminator", true); - - c.set ("discriminator", &m); - } - } - } - - virtual void - traverse_object_post (type& c) + traverse_object (type& c) { // Process indexes. Here we need to do two things: resolve member // names to member paths and assign names to unnamed indexes. We @@ -2767,7 +2089,7 @@ namespace relational typedef vector<relationship> relationships; virtual void - traverse_view_post (type& c) + traverse_view (type& c) { bool has_q (c.count ("query")); bool has_o (c.count ("objects")); @@ -3154,417 +2476,11 @@ namespace relational view_object& pointee_; }; - void - assign_pointer (type& c) - { - location_t loc (0); // Pragma location, or 0 if not used. - - try - { - string ptr; - string const& type (class_fq_name (c)); - - tree decl (0); // Resolved template node. - string decl_name; // User-provided template name. - tree resolve_scope (0); // Scope in which we resolve names. - - class_pointer const* cp (0); - bool cp_template (false); - - if (c.count ("pointer")) - { - cp = &c.get<class_pointer> ("pointer"); - } - // If we are a derived type in polymorphic hierarchy, then use - // our root's pointer type by default. - // - else if (semantics::class_* r = polymorphic (c)) - { - if (&c != r && r->count ("pointer-template")) - cp = r->get<class_pointer const*> ("pointer-template"); - } - - if (cp != 0) - { - string const& p (cp->name); - - if (p == "*") - { - ptr = type + "*"; - cp_template = true; - } - else if (p[p.size () - 1] == '*') - ptr = p; - else if (p.find ('<') != string::npos) - { - // Template-id. - // - ptr = p; - decl_name.assign (p, 0, p.find ('<')); - } - else - { - // This is not a template-id. Resolve it and see if it is a - // template or a type. - // - decl = resolve_name (p, cp->scope, true); - int tc (TREE_CODE (decl)); - - if (tc == TYPE_DECL) - { - ptr = p; - - // This can be a typedef'ed alias for a TR1 template-id. - // - if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (decl))) - { - decl = TI_TEMPLATE (ti); // DECL_TEMPLATE - - // Get to the most general template declaration. - // - while (DECL_TEMPLATE_INFO (decl)) - decl = DECL_TI_TEMPLATE (decl); - } - else - decl = 0; // Not a template. - } - else if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (decl)) - { - ptr = p + "< " + type + " >"; - decl_name = p; - cp_template = true; - } - else - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "does not name a type or a template" << endl; - - throw operation_failed (); - } - } - - // Resolve scope is the scope of the pragma. - // - resolve_scope = cp->scope; - loc = cp->loc; - } - else - { - // See if any of the namespaces containing this class specify - // a pointer. - // - for (semantics::scope* s (&c.scope ());; s = &s->scope_ ()) - { - using semantics::namespace_; - - namespace_* ns (dynamic_cast<namespace_*> (s)); - - if (ns == 0) - continue; // Some other scope. - - if (ns->extension ()) - ns = &ns->original (); - - if (!ns->count ("pointer")) - { - if (ns->global_scope ()) - break; - else - continue; - } - - cp = &ns->get<class_pointer> ("pointer"); - string const& p (cp->name); - - // Namespace-specified pointer can only be '*' or are template. - // - if (p == "*") - ptr = type + "*"; - else if (p[p.size () - 1] == '*') - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "at namespace level cannot be a raw pointer" << endl; - } - else if (p.find ('<') != string::npos) - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "at namespace level cannot be a template-id" << endl; - } - else - { - // Resolve this name and make sure it is a template. - // - decl = resolve_name (p, cp->scope, true); - int tc (TREE_CODE (decl)); - - if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (decl)) - { - ptr = p + "< " + type + " >"; - decl_name = p; - } - else - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "does not name a template" << endl; - } - } - - if (ptr.empty ()) - throw operation_failed (); - - cp_template = true; - - // Resolve scope is the scope of the pragma. - // - resolve_scope = cp->scope; - loc = cp->loc; - break; - } - - // Use the default pointer. - // - if (ptr.empty ()) - { - string const& p (options.default_pointer ()); - - if (p == "*") - ptr = type + "*"; - else - { - ptr = p + "< " + type + " >"; - decl_name = p; - } - - // Resolve scope is the scope of the class. - // - resolve_scope = c.scope ().tree_node (); - } - } - - // If this class is a root of a polymorphic hierarchy, then cache - // the pointer template so that we can use it for derived classes. - // - if (cp != 0 && cp_template && polymorphic (c) == &c) - c.set ("pointer-template", cp); - - // Check if we are using TR1. - // - if (decl != 0 || !decl_name.empty ()) - { - bool& tr1 (features.tr1_pointer); - bool& boost (features.boost_pointer); - - // First check the user-supplied name. - // - tr1 = tr1 - || decl_name.compare (0, 8, "std::tr1") == 0 - || decl_name.compare (0, 10, "::std::tr1") == 0; - - // If there was no match, also resolve the name since it can be - // a using-declaration for a TR1 template. - // - if (!tr1) - { - if (decl == 0) - decl = resolve_name (decl_name, resolve_scope, false); - - if (TREE_CODE (decl) != TEMPLATE_DECL || ! - DECL_CLASS_TEMPLATE_P (decl)) - { - // This is only checked for the --default-pointer option. - // - error (c.file (), c.line (), c.column ()) - << "name '" << decl_name << "' specified with the " - << "--default-pointer option does not name a class " - << "template" << endl; - - throw operation_failed (); - } - - string n (decl_as_string (decl, TFF_PLAIN_IDENTIFIER)); - - // In case of a boost TR1 implementation, we cannot distinguish - // between the boost:: and std::tr1:: usage since the latter is - // just a using-declaration for the former. - // - tr1 = tr1 - || n.compare (0, 8, "std::tr1") == 0 - || n.compare (0, 10, "::std::tr1") == 0; - - boost = boost - || n.compare (0, 17, "boost::shared_ptr") == 0 - || n.compare (0, 19, "::boost::shared_ptr") == 0; - } - } - - // Fully-qualify all the unqualified components of the name. - // - try - { - lex_.start (ptr); - ptr.clear (); - - string t; - bool punc (false); - bool scoped (false); - - for (cpp_ttype tt (lex_.next (t)); - tt != CPP_EOF; - tt = lex_.next (t)) - { - if (punc && tt > CPP_LAST_PUNCTUATOR) - ptr += ' '; - - punc = false; - - switch (static_cast<unsigned> (tt)) - { - case CPP_LESS: - { - ptr += "< "; - break; - } - case CPP_GREATER: - { - ptr += " >"; - break; - } - case CPP_COMMA: - { - ptr += ", "; - break; - } - case CPP_NAME: - { - // If the name was not preceeded with '::', look it - // up in the pragmas's scope and add the qualifer. - // - if (!scoped) - { - tree decl (resolve_name (t, resolve_scope, false)); - tree scope (CP_DECL_CONTEXT (decl)); - - if (scope != global_namespace) - { - ptr += "::"; - ptr += decl_as_string (scope, TFF_PLAIN_IDENTIFIER); - } - - ptr += "::"; - } - - ptr += t; - punc = true; - break; - } - case CPP_KEYWORD: - case CPP_NUMBER: - { - ptr += t; - punc = true; - break; - } - default: - { - ptr += t; - break; - } - } - - scoped = (tt == CPP_SCOPE); - } - } - catch (cxx_lexer::invalid_input const&) - { - throw operation_failed (); - } - - c.set ("object-pointer", ptr); - } - catch (invalid_name const& ex) - { - if (loc != 0) - error (loc) - << "name '" << ex.name () << "' specified with db pragma " - << "pointer is invalid" << endl; - else - error (c.file (), c.line (), c.column ()) - << "name '" << ex.name () << "' specified with the " - << "--default-pointer option is invalid" << endl; - - - throw operation_failed (); - } - catch (unable_to_resolve const& ex) - { - if (loc != 0) - error (loc) - << "unable to resolve name '" << ex.name () << "' specified " - << "with db pragma pointer" << endl; - else - error (c.file (), c.line (), c.column ()) - << "unable to resolve name '" << ex.name () << "' specified " - << "with the --default-pointer option" << endl; - - throw operation_failed (); - } - } - - private: - struct invalid_name - { - invalid_name (string const& n): name_ (n) {} - - string const& - name () const {return name_;} - - private: - string name_; - }; - - typedef lookup::unable_to_resolve unable_to_resolve; - - tree - resolve_name (string const& qn, tree scope, bool is_type) - { - try - { - string tl; - tree tn; - cpp_ttype tt, ptt; - - nlex_.start (qn); - tt = nlex_.next (tl, &tn); - - string name; - return lookup::resolve_scoped_name ( - nlex_, tt, tl, tn, ptt, scope, name, is_type); - } - catch (cxx_lexer::invalid_input const&) - { - throw invalid_name (qn); - } - catch (lookup::invalid_name const&) - { - throw invalid_name (qn); - } - } - private: cxx_string_lexer lex_; - cxx_string_lexer nlex_; // Nested lexer. data_member member_; traversal::names member_names_; - - semantics::type* std_string_; - semantics::names* std_string_hint_; - - tree access_; // odb::access node. }; } diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 56857f3..63ab860 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -864,7 +864,8 @@ namespace relational ++end; // Transform the range from [begin, end] to [begin, end). string const& type (class_fq_name (c)); - string traits ("access::object_traits< " + type + " >"); + string traits ("access::object_traits_impl< " + type + ", id_" + + db.string () + " >"); // create_schema () // @@ -941,7 +942,8 @@ namespace relational os << "static const schema_catalog_entry" << endl << "schema_catalog_entry_" << flat_name (type) << "_ (" << endl - << strlit (options.schema_name ()) << "," << endl + << "id_" << db << "," << endl + << strlit (options.schema_name ()[db]) << "," << endl << "&" << traits << "::create_schema);" << endl; } diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index 5a02703..7516801 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -18,8 +18,8 @@ traverse_object (type& c) using semantics::data_member; data_member* id (id_member (c)); - bool auto_id (id ? id->count ("auto") : false); - bool base_id (id ? &id->scope () != &c : false); // Comes from base. + bool auto_id (id && auto_ (*id)); + bool base_id (id && &id->scope () != &c); // Comes from base. member_access* id_ma (id ? &id->get<member_access> ("get") : 0); bool has_ptr (has_a (c, test_pointer)); @@ -49,7 +49,8 @@ traverse_object (type& c) } string const& type (class_fq_name (c)); - string traits ("access::object_traits< " + type + " >"); + string traits ("access::object_traits_impl< " + type + ", id_" + + db.string () + " >"); column_count_type const& cc (column_count (c)); os << "// " << class_name (c) << endl @@ -187,7 +188,7 @@ traverse_object (type& c) << "//" << endl << "if (--d != 0)" << "{" - << "if (object_traits<base_type>::grow (*i.base, " << + << "if (base_traits::grow (*i.base, " << "t + " << cols << "UL" << (poly_base != poly_root ? ", d" : "") << "))" << endl << "i.base->version++;" @@ -268,7 +269,7 @@ traverse_object (type& c) os << "// " << class_name (*poly_base) << " base" << endl << "//" << endl << "if (sk == statement_select)" << endl - << "object_traits<base_type>::"; + << "base_traits::"; if (poly_base == poly_root) os << "bind (b + n, *i.base, sk);"; @@ -360,7 +361,7 @@ traverse_object (type& c) os << "// " << class_name (*poly_base) << " base" << endl << "//" << endl << "if (--d != 0)" << endl - << "object_traits<base_type>::init (o, *i.base, db" << + << "base_traits::init (o, *i.base, db" << (poly_base != poly_root ? ", d" : "") << ");" << endl; } @@ -450,7 +451,8 @@ traverse_object (type& c) << "typeid (" << type << ")," << endl; if (poly_derived) - os << "&object_traits< " << class_fq_name (*poly_base) << " >::info"; + os << "&object_traits_impl< " << class_fq_name (*poly_base) << + ", id_" << db << " >::info"; else os << "0"; @@ -463,7 +465,7 @@ traverse_object (type& c) os << "," << endl << strlit (string (n, 2, string::npos)) << "," << endl << "&odb::create_impl< " << type << " >," << endl - << "&odb::dispatch_impl< " << type << " >," << endl; + << "&odb::dispatch_impl< " << type << ", id_" << db << " >," << endl; if (poly_derived) os << "&statements_type::delayed_loader"; @@ -883,7 +885,7 @@ traverse_object (type& c) // hierarchy. // if (poly_derived) - os << "object_traits<base_type>::persist (db, obj, false, false);" + os << "base_traits::persist (db, obj, false, false);" << endl; os << "image_type& im (sts.image ());" @@ -1135,7 +1137,7 @@ traverse_object (type& c) // if (!readonly_base) { - os << "object_traits<base_type>::update (db, obj, false, false);" + os << "base_traits::update (db, obj, false, false);" << endl; } else @@ -1550,7 +1552,7 @@ traverse_object (type& c) // Call our base last (we erase polymorphic objects from base // to derived in order not to trigger cascading deletes). // - os << "object_traits<base_type>::erase (db, id, false, false);" + os << "base_traits::erase (db, id, false, false);" << endl; } @@ -1787,7 +1789,7 @@ traverse_object (type& c) // Call our base last (we erase polymorphic objects from base // to derived in order not to trigger cascading deletes). // - os << "object_traits<base_type>::erase (db, obj, false, false);" + os << "base_traits::erase (db, obj, false, false);" << endl; } @@ -2349,7 +2351,7 @@ traverse_object (type& c) if (poly_derived) os << "if (--d != 0)" << endl - << "object_traits<base_type>::load_ (sts.base_statements (), obj" << + << "base_traits::load_ (sts.base_statements (), obj" << (poly_base != poly_root ? ", d" : "") << ");" << endl; @@ -2562,60 +2564,6 @@ traverse_object (type& c) if (options.generate_query ()) { - // query () - // - os << "result< " << traits << "::object_type >" << endl - << traits << "::" << endl - << "query (database&, const query_base_type& q)" - << "{" - << "using namespace " << db << ";" - << "using odb::details::shared;" - << "using odb::details::shared_ptr;" - << endl - << db << "::connection& conn (" << endl - << db << "::transaction::current ().connection ());" - << endl - << "statements_type& sts (" << endl - << "conn.statement_cache ().find_object<object_type> ());" - << endl; - - // Rebind the image if necessary. - // - os << "image_type& im (sts.image ());" - << "binding& imb (sts.select_image_binding (" << - (poly_derived ? "depth" : "") << "));" - << endl; - - if (poly_derived) - { - os << "if (imb.version == 0 ||" << endl - << "check_version (sts.select_image_versions (), im))" - << "{" - << "bind (imb.bind, 0, 0, im, statement_select);" - << "update_version (sts.select_image_versions ()," << endl - << "im," << endl - << "sts.select_image_bindings ());" - << "}"; - } - else - { - os << "if (im.version != sts.select_image_version () ||" << endl - << "imb.version == 0)" - << "{" - << "bind (imb.bind, im, statement_select);" - << "sts.select_image_version (im.version);" - << "imb.version++;" - << "}"; - } - - os << "shared_ptr<select_statement> st (" << endl - << "new (shared) select_statement (" << endl; - object_query_statement_ctor_args (c); - os << "));" << endl - << "st->execute ();"; - - post_query_ (c); - char const* result_type; if (poly) result_type = "polymorphic_object_result_impl<object_type>"; @@ -2624,13 +2572,73 @@ traverse_object (type& c) else result_type = "no_id_object_result_impl<object_type>"; - os << endl - << "shared_ptr< odb::" << result_type << " > r (" << endl - << "new (shared) " << db << "::" << result_type << " (" << endl - << "q, st, sts));" - << endl - << "return result<object_type> (r);" - << "}"; + // Unprepared. + // + if (!options.omit_unprepared ()) + { + // query () + // + os << "result< " << traits << "::object_type >" << endl + << traits << "::" << endl + << "query (database&, const query_base_type& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" + << endl + << "statements_type& sts (" << endl + << "conn.statement_cache ().find_object<object_type> ());" + << endl; + + // Rebind the image if necessary. + // + os << "image_type& im (sts.image ());" + << "binding& imb (sts.select_image_binding (" << + (poly_derived ? "depth" : "") << "));" + << endl; + + if (poly_derived) + { + os << "if (imb.version == 0 ||" << endl + << "check_version (sts.select_image_versions (), im))" + << "{" + << "bind (imb.bind, 0, 0, im, statement_select);" + << "update_version (sts.select_image_versions ()," << endl + << "im," << endl + << "sts.select_image_bindings ());" + << "}"; + } + else + { + os << "if (im.version != sts.select_image_version () ||" << endl + << "imb.version == 0)" + << "{" + << "bind (imb.bind, im, statement_select);" + << "sts.select_image_version (im.version);" + << "imb.version++;" + << "}"; + } + + os << "q.init_parameters ();" + << "shared_ptr<select_statement> st (" << endl + << "new (shared) select_statement (" << endl; + object_query_statement_ctor_args (c, "q", false); + os << "));" << endl + << "st->execute ();"; + + post_query_ (c, true); + + os << endl + << "shared_ptr< odb::" << result_type << " > r (" << endl + << "new (shared) " << db << "::" << result_type << " (" << endl + << "q, st, sts));" + << endl + << "return result<object_type> (r);" + << "}"; + } // erase_query // @@ -2642,12 +2650,142 @@ traverse_object (type& c) << db << "::connection& conn (" << endl << db << "::transaction::current ().connection ());" << endl + << "q.init_parameters ();" << "delete_statement st (" << endl; object_erase_query_statement_ctor_args (c); os << ");" << endl << "return st.execute ();" << "}"; + + // Prepared. Very similar to unprepared but has some annoying variations + // that make it difficult to factor out something common. + // + if (options.generate_prepared ()) + { + os << "odb::details::shared_ptr<prepared_query_impl>" << endl + << traits << "::" << endl + << "prepare_query (connection& c, const char* n, " << + "const query_base_type& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::connection& conn (" << endl + << "static_cast<" << db << "::connection&> (c));" + << endl + << "statements_type& sts (" << endl + << "conn.statement_cache ().find_object<object_type> ());" + << endl; + + // Rebind the image if necessary. + // + os << "image_type& im (sts.image ());" + << "binding& imb (sts.select_image_binding (" << + (poly_derived ? "depth" : "") << "));" + << endl; + + if (poly_derived) + { + os << "if (imb.version == 0 ||" << endl + << "check_version (sts.select_image_versions (), im))" + << "{" + << "bind (imb.bind, 0, 0, im, statement_select);" + << "update_version (sts.select_image_versions ()," << endl + << "im," << endl + << "sts.select_image_bindings ());" + << "}"; + } + else + { + os << "if (im.version != sts.select_image_version () ||" << endl + << "imb.version == 0)" + << "{" + << "bind (imb.bind, im, statement_select);" + << "sts.select_image_version (im.version);" + << "imb.version++;" + << "}"; + } + + os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl + << "new (shared) " << db << "::prepared_query_impl (conn));" + << "r->name = n;" + << "r->execute = &execute_query;" + << "r->query = q;" + << "r->stmt.reset (" << endl + << "new (shared) select_statement (" << endl; + object_query_statement_ctor_args (c, "r->query", true); + os << "));" + << endl + << "return r;" + << "}"; + + os << "odb::details::shared_ptr<result_impl>" << endl + << traits << "::" << endl + << "execute_query (prepared_query_impl& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::prepared_query_impl& pq (" << endl + << "static_cast<" << db << "::prepared_query_impl&> (q));" + << "shared_ptr<select_statement> st (" << endl + << "odb::details::inc_ref (" << endl + << "static_cast<select_statement*> (pq.stmt.get ())));" + << endl + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" + << endl + << "// The connection used by the current transaction and the" << endl + << "// one used to prepare this statement must be the same." << endl + << "//" << endl + << "assert (&conn == &st->connection ());" + << endl + << "statements_type& sts (" << endl + << "conn.statement_cache ().find_object<object_type> ());" + << endl; + + // Rebind the image if necessary. + // + os << "image_type& im (sts.image ());" + << "binding& imb (sts.select_image_binding (" << + (poly_derived ? "depth" : "") << "));" + << endl; + + if (poly_derived) + { + os << "if (imb.version == 0 ||" << endl + << "check_version (sts.select_image_versions (), im))" + << "{" + << "bind (imb.bind, 0, 0, im, statement_select);" + << "update_version (sts.select_image_versions ()," << endl + << "im," << endl + << "sts.select_image_bindings ());" + << "}"; + } + else + { + os << "if (im.version != sts.select_image_version () ||" << endl + << "imb.version == 0)" + << "{" + << "bind (imb.bind, im, statement_select);" + << "sts.select_image_version (im.version);" + << "imb.version++;" + << "}"; + } + + os << "pq.query.init_parameters ();" + << "st->execute ();"; + post_query_ (c, false); + + os << endl + << "return shared_ptr<result_impl> (" << endl + << "new (shared) " << db << "::" << result_type << " (" << endl + << "pq.query, st, sts));" + << "}"; + } } if (embedded_schema) @@ -2658,7 +2796,8 @@ void relational::source::class_:: traverse_view (type& c) { string const& type (class_fq_name (c)); - string traits ("access::view_traits< " + type + " >"); + string traits ("access::view_traits_impl< " + type + ", id_" + + db.string () + " >"); os << "// " << class_name (c) << endl << "//" << endl @@ -3391,54 +3530,157 @@ traverse_view (type& c) << "}"; } - // query () + // Unprepared. // - os << "result< " << traits << "::view_type >" << endl - << traits << "::" << endl - << "query (database&, const query_base_type& q)" - << "{" - << "using namespace " << db << ";" - << "using odb::details::shared;" - << "using odb::details::shared_ptr;" - << endl - << db << "::connection& conn (" << endl - << db << "::transaction::current ().connection ());" - << endl - << "view_statements< view_type >& sts (" << endl - << "conn.statement_cache ().find_view<view_type> ());" - << endl - << "image_type& im (sts.image ());" - << "binding& imb (sts.image_binding ());" - << endl - << "if (im.version != sts.image_version () || imb.version == 0)" - << "{" - << "bind (imb.bind, im);" - << "sts.image_version (im.version);" - << "imb.version++;" - << "}"; + if (!options.omit_unprepared ()) + { + os << "result< " << traits << "::view_type >" << endl + << traits << "::" << endl + << "query (database&, const query_base_type& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" + << endl + << "statements_type& sts (" << endl + << "conn.statement_cache ().find_view<view_type> ());" + << endl + << "image_type& im (sts.image ());" + << "binding& imb (sts.image_binding ());" + << endl + << "if (im.version != sts.image_version () || imb.version == 0)" + << "{" + << "bind (imb.bind, im);" + << "sts.image_version (im.version);" + << "imb.version++;" + << "}"; - if (vq.kind == view_query::runtime) - os << "const query_base_type& qs (q);"; - else - os << "const query_base_type& qs (query_statement (q));"; + if (vq.kind == view_query::runtime) + os << "const query_base_type& qs (q);"; + else + os << "const query_base_type& qs (query_statement (q));"; - os << "shared_ptr<select_statement> st (" << endl - << "new (shared) select_statement (" << endl; + os << "qs.init_parameters ();" + << "shared_ptr<select_statement> st (" << endl + << "new (shared) select_statement (" << endl; + view_query_statement_ctor_args (c, "qs", false); + os << "));" << endl + << "st->execute ();"; - view_query_statement_ctor_args (c); + post_query_ (c, true); - os << "));" << endl - << "st->execute ();"; + os << endl + << "shared_ptr< odb::view_result_impl<view_type> > r (" << endl + << "new (shared) " << db << "::view_result_impl<view_type> (" << endl + << "qs, st, sts));" + << endl + << "return result<view_type> (r);" + << "}"; + } - post_query_ (c); + // Prepared. Very similar to unprepared but has some annoying variations + // that make it difficult to factor out something common. + // + if (options.generate_prepared ()) + { + os << "odb::details::shared_ptr<prepared_query_impl>" << endl + << traits << "::" << endl + << "prepare_query (connection& c, const char* n, " << + "const query_base_type& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::connection& conn (" << endl + << "static_cast<" << db << "::connection&> (c));" + << endl + << "statements_type& sts (" << endl + << "conn.statement_cache ().find_view<view_type> ());" + << endl; - os << endl - << "shared_ptr< odb::view_result_impl<view_type> > r (" << endl - << "new (shared) " << db << "::view_result_impl<view_type> (" << endl - << "qs, st, sts));" - << endl - << "return result<view_type> (r);" - << "}"; + // Rebind the image if necessary. + // + os << "image_type& im (sts.image ());" + << "binding& imb (sts.image_binding ());" + << endl + << "if (im.version != sts.image_version () || imb.version == 0)" + << "{" + << "bind (imb.bind, im);" + << "sts.image_version (im.version);" + << "imb.version++;" + << "}"; + + os << "shared_ptr<" << db << "::prepared_query_impl> r (" << endl + << "new (shared) " << db << "::prepared_query_impl (conn));" + << "r->name = n;" + << "r->execute = &execute_query;"; + + if (vq.kind == view_query::runtime) + os << "r->query = q;"; + else + os << "r->query = query_statement (q);"; + + os << "r->stmt.reset (" << endl + << "new (shared) select_statement (" << endl; + view_query_statement_ctor_args (c, "r->query", true); + os << "));" + << endl + << "return r;" + << "}"; + + os << "odb::details::shared_ptr<result_impl>" << endl + << traits << "::" << endl + << "execute_query (prepared_query_impl& q)" + << "{" + << "using namespace " << db << ";" + << "using odb::details::shared;" + << "using odb::details::shared_ptr;" + << endl + << db << "::prepared_query_impl& pq (" << endl + << "static_cast<" << db << "::prepared_query_impl&> (q));" + << "shared_ptr<select_statement> st (" << endl + << "odb::details::inc_ref (" << endl + << "static_cast<select_statement*> (pq.stmt.get ())));" + << endl + << db << "::connection& conn (" << endl + << db << "::transaction::current ().connection ());" + << endl + << "// The connection used by the current transaction and the" << endl + << "// one used to prepare this statement must be the same." << endl + << "//" << endl + << "assert (&conn == &st->connection ());" + << endl + << "statements_type& sts (" << endl + << "conn.statement_cache ().find_view<view_type> ());" + << endl; + + // Rebind the image if necessary. + // + os << "image_type& im (sts.image ());" + << "binding& imb (sts.image_binding ());" + << endl + << "if (im.version != sts.image_version () || imb.version == 0)" + << "{" + << "bind (imb.bind, im);" + << "sts.image_version (im.version);" + << "imb.version++;" + << "}"; + + os << "pq.query.init_parameters ();" + << "st->execute ();"; + + post_query_ (c, false); + + os << endl + << "return shared_ptr<result_impl> (" << endl + << "new (shared) " << db << "::view_result_impl<view_type> (" << endl + << "pq.query, st, sts));" + << "}"; + } } namespace relational diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index b73cd01..8d57b1b 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -937,8 +937,9 @@ namespace relational virtual void traverse_composite (member_info& mi) { - os << "composite_value_traits< " << mi.fq_type () << - " >::bind (b + n, " << arg << "." << mi.var << "value, sk);"; + os << "composite_value_traits< " << mi.fq_type () << ", id_" << + db << " >::bind (" << endl + << "b + n, " << arg << "." << mi.var << "value, sk);"; } protected: @@ -973,8 +974,12 @@ namespace relational os << "if (sk != statement_update)" << "{"; - os << (obj ? "object" : "composite_value") << "_traits< " << - class_fq_name (c) << " >::bind (b + n, i, sk);"; + if (obj) + os << "object_traits_impl< "; + else + os << "composite_value_traits< "; + + os << class_fq_name (c) << ", id_" << db << " >::bind (b + n, i, sk);"; column_count_type const& cc (column_count (c)); @@ -1067,8 +1072,15 @@ namespace relational os << "// " << class_name (c) << " base" << endl << "//" << endl; - os << "if (" << (obj ? "object" : "composite_value") << "_traits< " << - class_fq_name (c) << " >::grow (i, t + " << index_ << "UL))" << endl + os << "if ("; + + if (obj) + os << "object_traits_impl< "; + else + os << "composite_value_traits< "; + + os << class_fq_name (c) << ", id_" << db << " >::grow (" << endl + << "i, t + " << index_ << "UL))" << endl << "grew = true;" << endl; @@ -1232,10 +1244,11 @@ namespace relational if (null (mi.m, key_prefix_) && mi.wrapper->template get<bool> ("wrapper-null-handler")) { - os << "if (wrapper_traits< " + wt + " >::get_null (" << + os << "if (wrapper_traits< " << wt << " >::get_null (" << member << "))" << endl - << "composite_value_traits< " + mi.fq_type () + " >::" << - "set_null (i." << mi.var << "value, sk);" + << "composite_value_traits< " << mi.fq_type () << ", id_" << + db << " >::set_null (" << endl + << "i." << mi.var << "value, sk);" << "else" << "{"; } @@ -1307,7 +1320,8 @@ namespace relational } if (comp) - traits = "composite_value_traits< " + type + " >"; + traits = "composite_value_traits< " + type + ", id_" + + db.string () + " >"; else { db_type_id = member_database_type_id_->database_type_id (mi.m); @@ -1403,8 +1417,12 @@ namespace relational if (generate_grow) os << "if ("; - os << (obj ? "object" : "composite_value") << "_traits< " << - class_fq_name (c) << " >::init (i, o, sk)"; + if (obj) + os << "object_traits_impl< "; + else + os << "composite_value_traits< "; + + os << class_fq_name (c) << ", id_" << db << " >::init (i, o, sk)"; if (generate_grow) os << ")" << endl @@ -1571,9 +1589,10 @@ namespace relational if (null (mi.m, key_prefix_) && mi.wrapper->template get<bool> ("wrapper-null-handler")) { - os << "if (composite_value_traits< " + mi.fq_type () + " >::" << - "get_null (i." << mi.var << "value))" << endl - << "wrapper_traits< " + wt + " >::set_null (" << member + ");" + os << "if (composite_value_traits< " << mi.fq_type () << + ", id_" << db << " >::get_null (" << endl + << "i." << mi.var << "value))" << endl + << "wrapper_traits< " << wt << " >::set_null (" << member + ");" << "else" << endl; } @@ -1595,8 +1614,9 @@ namespace relational os << "if ("; if (comp) - os << "composite_value_traits< " + type + " >::get_null (i." << - mi.var << "value)"; + os << "composite_value_traits< " << type << ", id_" << db << + " >::get_null (" << endl + << "i." << mi.var << "value)"; else get_null (mi); @@ -1618,7 +1638,8 @@ namespace relational type = mi.fq_type (); if (comp) - traits = "composite_value_traits< " + type + " >"; + traits = "composite_value_traits< " + type + ", id_" + + db.string () + " >"; else { db_type_id = member_database_type_id_->database_type_id (mi.m); @@ -1645,7 +1666,8 @@ namespace relational semantics::type& pt (member_utype (mi.m, key_prefix_)); if (lazy_pointer (pt)) - os << member << " = ptr_traits::pointer_type (*db, id);"; + os << member << " = ptr_traits::pointer_type (" << endl + << "*static_cast<" << db << "::database*> (db), id);"; else { os << "// If a compiler error points to the line below, then" << endl @@ -1653,7 +1675,8 @@ namespace relational << "// cannot be initialized from an object pointer." << endl << "//" << endl << member << " = ptr_traits::pointer_type (" << endl - << "db->load< obj_traits::object_type > (id));"; + << "static_cast<" << db << "::database*> (db)->load<" << endl + << " obj_traits::object_type > (id));"; // If we are loading into an eager weak pointer, make sure there // is someone else holding a strong pointer to it (normally a @@ -1730,9 +1753,14 @@ namespace relational return; os << "// " << class_name (c) << " base" << endl - << "//" << endl - << (obj ? "object" : "composite_value") << "_traits< " << - class_fq_name (c) << " >::init (o, i, db);" + << "//" << endl; + + if (obj) + os << "object_traits_impl< "; + else + os << "composite_value_traits< "; + + os << class_fq_name (c) << ", id_" << db << " >::init (o, i, db);" << endl; } }; @@ -1750,12 +1778,11 @@ namespace relational false), c_ (c) { - string const& type (class_fq_name (c)); + scope_ = object (c) + ? "access::object_traits_impl< " + : "access::composite_value_traits< "; - if (object (c)) - scope_ = "access::object_traits< " + type + " >"; - else - scope_ = "access::composite_value_traits< " + type + " >"; + scope_ += class_fq_name (c) + ", id_" + db.string () + " >"; } // Unless the database system can execute several interleaving @@ -3381,7 +3408,7 @@ namespace relational // virtual void - post_query_ (type&) + post_query_ (type&, bool /*once_off*/) { } @@ -3400,11 +3427,13 @@ namespace relational } virtual void - object_query_statement_ctor_args (type&) + object_query_statement_ctor_args (type&, + std::string const& q, + bool /*prepared*/) { - os << "sts.connection ()," << endl - << "query_statement + q.clause ()," << endl - << "q.parameters_binding ()," << endl + os << "conn," << endl + << "query_statement + " << q << ".clause ()," << endl + << q << ".parameters_binding ()," << endl << "imb"; } @@ -3429,11 +3458,13 @@ namespace relational } virtual void - view_query_statement_ctor_args (type&) + view_query_statement_ctor_args (type&, + string const& q, + bool /*prepared*/) { - os << "sts.connection ()," << endl - << "qs.clause ()," << endl - << "qs.parameters_binding ()," << endl + os << "conn," << endl + << q << ".clause ()," << endl + << q << ".parameters_binding ()," << endl << "imb"; } @@ -3469,7 +3500,8 @@ namespace relational traverse_composite (type& c) { string const& type (class_fq_name (c)); - string traits ("access::composite_value_traits< " + type + " >"); + string traits ("access::composite_value_traits< " + type + ", id_" + + db.string () + " >"); os << "// " << class_name (c) << endl << "//" << endl @@ -3637,9 +3669,6 @@ namespace relational if (embedded_schema) os << "#include <odb/schema-catalog-impl.hxx>" << endl; - if (options.generate_query ()) - os << "#include <odb/details/shared-ptr.hxx>" << endl; - os << endl; os << "#include <odb/" << db << "/traits.hxx>" << endl @@ -3666,6 +3695,9 @@ namespace relational if (options.generate_query ()) { + if (options.generate_prepared ()) + os << "#include <odb/" << db << "/prepared-query.hxx>" << endl; + if (features.simple_object) os << "#include <odb/" << db << "/simple-object-result.hxx>" << endl; diff --git a/odb/relational/sqlite/common.cxx b/odb/relational/sqlite/common.cxx index 7164ef3..601b01d 100644 --- a/odb/relational/sqlite/common.cxx +++ b/odb/relational/sqlite/common.cxx @@ -78,7 +78,8 @@ namespace relational void member_image_type:: traverse_composite (member_info& mi) { - type_ = "composite_value_traits< " + mi.fq_type () + " >::image_type"; + type_ = "composite_value_traits< " + mi.fq_type () + + ", id_sqlite >::image_type"; } void member_image_type:: diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx index 03467cc..731afba 100644 --- a/odb/relational/sqlite/source.cxx +++ b/odb/relational/sqlite/source.cxx @@ -123,7 +123,7 @@ namespace relational traverse_composite (member_info& mi) { os << "if (composite_value_traits< " << mi.fq_type () << - " >::grow (" << endl + ", id_sqlite >::grow (" << endl << "i." << mi.var << "value, t + " << index_ << "UL))" << "{" << "grew = true;" diff --git a/odb/relational/validator.cxx b/odb/relational/validator.cxx index 1269406..9d14571 100644 --- a/odb/relational/validator.cxx +++ b/odb/relational/validator.cxx @@ -21,11 +21,228 @@ namespace relational // Pass 2. // + struct data_member2: traversal::data_member, context + { + data_member2 (bool& valid) + : valid_ (valid) + { + } + + virtual void + traverse (type& m) + { + if (transient (m)) + return; + + if (null (m)) + { + if (semantics::class_* c = composite_wrapper (utype (m))) + { + if (has_a (*c, test_container)) + { + os << m.file () << ":" << m.line () << ":" << m.column () << ":" + << " error: composite member containing containers cannot " + << "be null" << endl; + + os << c->file () << ":" << c->line () << ":" << c->column () + << ": info: composite value type is defined here" << endl; + + valid_ = false; + } + } + } + } + + bool& valid_; + }; + + struct object_no_id_members: object_members_base + { + object_no_id_members (bool& valid) + : object_members_base (false, false, true), valid_ (valid), dm_ (0) + { + } + + virtual void + traverse_pointer (semantics::data_member& m, semantics::class_&) + { + if (inverse (m)) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: inverse object pointer member '" << member_prefix_ + << m.name () << "' in an object without an object id" << endl; + + valid_ = false; + } + } + + virtual void + traverse_container (semantics::data_member& m, semantics::type&) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: container member '" << member_prefix_ << m.name () + << "' in an object without an object id" << endl; + + valid_ = false; + } + + virtual void + traverse_composite (semantics::data_member* m, semantics::class_& c) + { + semantics::data_member* old_dm (dm_); + + if (dm_ == 0) + dm_ = m; + + object_members_base::traverse_composite (m, c); + + dm_ = old_dm; + } + + private: + bool& valid_; + semantics::data_member* dm_; // Direct object data member. + }; + + struct composite_id_members: object_members_base + { + composite_id_members (bool& valid) + : object_members_base (false, false, true), valid_ (valid), dm_ (0) + { + } + + virtual void + traverse_pointer (semantics::data_member& m, semantics::class_&) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: object pointer member '" << member_prefix_ << m.name () + << "' in a composite value type that is used as an object id" + << endl; + + valid_ = false; + } + + virtual void + traverse_simple (semantics::data_member& m) + { + if (readonly (member_path_, member_scope_)) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: readonly member '" << member_prefix_ << m.name () + << "' in a composite value type that is used as an object id" + << endl; + + valid_ = false; + } + } + + virtual void + traverse_container (semantics::data_member& m, semantics::type&) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: container member '" << member_prefix_ << m.name () + << "' in a composite value type that is used as an object id" + << endl; + + valid_ = false; + } + + virtual void + traverse_composite (semantics::data_member* m, semantics::class_& c) + { + semantics::data_member* old_dm (dm_); + + if (dm_ == 0) + dm_ = m; + + object_members_base::traverse_composite (m, c); + + dm_ = old_dm; + } + + private: + bool& valid_; + semantics::data_member* dm_; // Direct composite member. + }; + + struct view_members: object_members_base + { + view_members (bool& valid) + : object_members_base (false, false, true), valid_ (valid), dm_ (0) + { + } + + virtual void + traverse_simple (semantics::data_member& m) + { + if (object_pointer (utype (m))) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: view data member '" << member_prefix_ << m.name () + << "' is an object pointer" << endl; + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << ": info: views cannot contain object pointers" << endl; + + valid_ = false; + } + } + + virtual void + traverse_container (semantics::data_member& m, semantics::type&) + { + semantics::data_member& dm (dm_ != 0 ? *dm_ : m); + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << " error: view data member '" << member_prefix_ << m.name () + << "' is a container" << endl; + + os << dm.file () << ":" << dm.line () << ":" << dm.column () << ":" + << ": info: views cannot contain containers" << endl; + + valid_ = false; + } + + virtual void + traverse_composite (semantics::data_member* m, semantics::class_& c) + { + semantics::data_member* old_dm (dm_); + + if (dm_ == 0) + dm_ = m; + + object_members_base::traverse_composite (m, c); + + dm_ = old_dm; + } + + private: + bool& valid_; + semantics::data_member* dm_; // Direct view data member. + }; + struct class2: traversal::class_, context { class2 (bool& valid) - : valid_ (valid) + : valid_ (valid), + data_member_ (valid), + object_no_id_members_ (valid), + composite_id_members_ (valid), + view_members_ (valid) { + *this >> data_member_names_ >> data_member_; } virtual void @@ -56,6 +273,66 @@ namespace relational virtual void traverse_object (type& c) { + semantics::data_member* id (id_member (c)); + + if (id != 0) + { + if (semantics::class_* cm = composite_wrapper (utype (*id))) + { + // Composite id cannot be auto. + // + if (auto_ (*id)) + { + os << id->file () << ":" << id->line () << ":" << id->column () + << ": error: composite id cannot be automatically assigned" + << endl; + + valid_ = false; + } + + // Make sure we don't have any containers or pointers in this + // composite value type. + // + if (valid_) + { + composite_id_members_.traverse (*cm); + + if (!valid_) + os << id->file () << ":" << id->line () << ":" << id->column () + << ": info: composite id is defined here" << endl; + } + + // Check that the composite value type is default-constructible. + // + if (!cm->default_ctor ()) + { + os << cm->file () << ":" << cm->line () << ":" << cm->column () + << ": error: composite value type that is used as object id " + << "is not default-constructible" << endl; + + os << cm->file () << ":" << cm->line () << ":" << cm->column () + << ": info: provide default constructor for this value type" + << endl; + + os << id->file () << ":" << id->line () << ":" << id->column () + << ": info: composite id is defined here" << endl; + + valid_ = false; + } + } + } + else + { + if (!abstract (c)) + { + // Make sure we don't have any containers or inverse pointers. + // + object_no_id_members_.traverse (c); + } + } + + names (c); + // Validate indexes. // { @@ -90,17 +367,30 @@ namespace relational } virtual void - traverse_view (type&) + traverse_view (type& c) { + // Make sure we don't have any containers or object pointers. + // + view_members_.traverse (c); + + names (c); } virtual void - traverse_composite (type&) + traverse_composite (type& c) { + names (c); } public: bool& valid_; + + data_member2 data_member_; + traversal::names data_member_names_; + + object_no_id_members object_no_id_members_; + composite_id_members composite_id_members_; + view_members view_members_; }; } |