From 5ebd62ec778bc8c9540e2379e764ac52c060adfc Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 9 Apr 2013 10:03:32 +0200 Subject: Generate embedded schema in single function instead of one per object --- odb/generator.cxx | 12 +- odb/relational/generate.hxx | 11 +- odb/relational/header.cxx | 9 -- odb/relational/model.hxx | 11 -- odb/relational/schema-source.cxx | 114 ++++++++++++++--- odb/relational/schema-source.hxx | 119 +++++++++++++----- odb/relational/schema.cxx | 6 - odb/relational/schema.hxx | 263 --------------------------------------- odb/relational/source.cxx | 5 - odb/relational/source.hxx | 2 - 10 files changed, 200 insertions(+), 352 deletions(-) diff --git a/odb/generator.cxx b/odb/generator.cxx index 5c9e897..8f49368 100644 --- a/odb/generator.cxx +++ b/odb/generator.cxx @@ -683,6 +683,11 @@ generate (options const& ops, case database::sqlite: { relational::source::generate (); + + if (gen_schema && + ops.schema_format ()[db].count (schema_format::embedded)) + relational::schema::generate_source (); + break; } } @@ -726,7 +731,10 @@ generate (options const& ops, "// Begin prologue.\n//", "//\n// End prologue."); - sch << "#include " << ctx->process_include_path (hxx_name) << endl + sch << "#include " << endl + << "#include " << endl + << endl + << "#include " << endl << endl; { @@ -742,7 +750,7 @@ generate (options const& ops, case database::pgsql: case database::sqlite: { - relational::schema_source::generate (); + relational::schema::generate_source (); break; } case database::common: diff --git a/odb/relational/generate.hxx b/odb/relational/generate.hxx index 5bd795e..3cbc363 100644 --- a/odb/relational/generate.hxx +++ b/odb/relational/generate.hxx @@ -33,12 +33,6 @@ namespace relational generate (); } - namespace schema_source - { - void - generate (); - } - namespace model { cutl::shared_ptr @@ -77,6 +71,11 @@ namespace relational void generate_migrate_post (semantics::relational::changeset&); + + // Generate embedded schema. + // + void + generate_source (); } } diff --git a/odb/relational/header.cxx b/odb/relational/header.cxx index bc63655..04a73a2 100644 --- a/odb/relational/header.cxx +++ b/odb/relational/header.cxx @@ -544,15 +544,6 @@ traverse_object (type& c) } } - // create_schema () - // - if (embedded_schema || separate_schema) - { - os << "static bool" << endl - << "create_schema (database&, unsigned short pass, bool drop);" - << endl; - } - object_public_extra_post (c); // Implementation details. diff --git a/odb/relational/model.hxx b/odb/relational/model.hxx index 44f01c9..c50b6b5 100644 --- a/odb/relational/model.hxx +++ b/odb/relational/model.hxx @@ -694,11 +694,7 @@ namespace relational // user knows what they are doing and skip it. // if (tables_.count (name)) - { - c.set ("model-range-first", model_.names_end ()); - c.set ("model-range-last", model_.names_end ()); return; - } string id (class_fq_name (c), 2); // Remove leading '::'. @@ -706,8 +702,6 @@ namespace relational t.set ("cxx-location", c.location ()); model_.new_edge (model_, t, name); - sema_rel::model::names_iterator begin (--model_.names_end ()); - // Add columns. // { @@ -731,11 +725,6 @@ namespace relational instance mc (model_); mc->traverse (c); } - - sema_rel::model::names_iterator end (--model_.names_end ()); - - c.set ("model-range-first", begin); - c.set ("model-range-last", end); } protected: diff --git a/odb/relational/schema-source.cxx b/odb/relational/schema-source.cxx index fcd1c68..e20529d 100644 --- a/odb/relational/schema-source.cxx +++ b/odb/relational/schema-source.cxx @@ -9,36 +9,116 @@ using namespace std; namespace relational { - namespace schema_source + namespace schema { void - generate () + generate_source () { context ctx; ostream& os (ctx.os); + database db (ctx.db); + options const& ops (ctx.options); + sema_rel::model& model (*ctx.model); + string const& schema_name (ops.schema_name ()[db]); - traversal::unit unit; - traversal::defines unit_defines; - traversal::namespace_ ns; - instance c; + instance emitter; + emitter_ostream emitter_os (*emitter); + schema_format format (schema_format::embedded); - unit >> unit_defines >> ns; - unit_defines >> c; + if (!model.names_empty ()) + { + os << "namespace odb" + << "{" + << "static bool" << endl + << "create_schema (database& db, unsigned short pass, bool drop)" + << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << "ODB_POTENTIALLY_UNUSED (pass);" + << "ODB_POTENTIALLY_UNUSED (drop);" + << endl; - traversal::defines ns_defines; + // Drop. + // + if (!ops.omit_drop ()) + { + bool close (false); - ns >> ns_defines >> ns; - ns_defines >> c; + os << "if (drop)" + << "{"; - instance i; - i->generate (); + instance dmodel (*emitter, emitter_os, format); + instance dtable (*emitter, emitter_os, format); + trav_rel::qnames names; + dmodel >> names >> dtable; - os << "namespace odb" - << "{"; + for (unsigned short pass (1); pass < 3; ++pass) + { + emitter->pass (pass); + dmodel->pass (pass); + dtable->pass (pass); - unit.dispatch (ctx.unit); + dmodel->traverse (model); - os << "}"; + close = close || !emitter->empty (); + } + + if (close) // Close the last case and the switch block. + os << "return false;" + << "}" // case + << "}"; // switch + + os << "}"; + } + + // Create. + // + if (!ops.omit_create ()) + { + bool close (false); + + if (ops.omit_drop ()) + os << "if (!drop)"; + else + os << "else"; + + os << "{"; + + instance cmodel (*emitter, emitter_os, format); + instance ctable (*emitter, emitter_os, format); + trav_rel::qnames names; + cmodel >> names >> ctable; + + for (unsigned short pass (1); pass < 3; ++pass) + { + emitter->pass (pass); + cmodel->pass (pass); + ctable->pass (pass); + + cmodel->traverse (model); + + close = close || !emitter->empty (); + } + + if (close) // Close the last case and the switch block. + os << "return false;" + << "}" // case + << "}"; // switch + + os << "}"; + } + + os << "return false;" + << "}"; + + os << "static const schema_catalog_entry" << endl + << "create_schema_entry_ (" << endl + << "id_" << db << "," << endl + << context::strlit (schema_name) << "," << endl + << "&create_schema);" + << endl; + + os << "}"; + } } } } diff --git a/odb/relational/schema-source.hxx b/odb/relational/schema-source.hxx index 798738d..4ed5827 100644 --- a/odb/relational/schema-source.hxx +++ b/odb/relational/schema-source.hxx @@ -7,62 +7,119 @@ #include +#include #include #include namespace relational { - namespace schema_source + namespace schema { - struct class_: traversal::class_, virtual context + struct cxx_emitter: emitter, virtual context { - typedef class_ base; + typedef cxx_emitter base; - virtual void - traverse (type& c) + void + pass (unsigned short p) { - if (!options.at_once () && class_file (c) != unit.file ()) - return; - - if (!object (c)) - return; - - if (abstract (c) && !polymorphic (c)) - return; + empty_ = true; + pass_ = p; + new_pass_ = true; - os << "// " << class_name (c) << endl - << "//" << endl - << endl; + if (pass_ == 1) + empty_passes_ = 0; // New set of passes. - schema_->traverse (c); + // Assume this pass is empty. + // + empty_passes_++; } - private: - instance schema_; - }; - - struct include: virtual context - { - typedef include base; + // Did this pass produce anything? + // + bool + empty () const + { + return empty_; + } virtual void - generate () + pre () { - extra_pre (); - os << "#include " << endl; - extra_post (); - os << endl; + first_ = true; } virtual void - extra_pre () + line (const string& l) { + if (l.empty ()) + return; // Ignore empty lines. + + if (first_) + { + first_ = false; + + // If this line starts a new pass, then output the switch/case + // blocks. + // + if (new_pass_) + { + new_pass_ = false; + empty_ = false; + empty_passes_--; // This pass is not empty. + + // Output case statements for empty preceeding passes, if any. + // + if (empty_passes_ != 0) + { + unsigned short s (pass_ - empty_passes_); + + if (s == 1) + os << "switch (pass)" + << "{"; + else + os << "return true;" // One more pass. + << "}"; + + for (; s != pass_; ++s) + os << "case " << s << ":" << endl; + + os << "{"; + empty_passes_ = 0; + } + + if (pass_ == 1) + os << "switch (pass)" + << "{"; + else + os << "return true;" // One more pass. + << "}"; + + os << "case " << pass_ << ":" << endl + << "{"; + } + + os << "db.execute ("; + } + else + os << strlit (line_ + '\n') << endl; + + line_ = l; } virtual void - extra_post () + post () { + if (!first_) // Ignore empty statements. + os << strlit (line_) << ");"; } + + private: + std::string line_; + bool first_; + bool empty_; + bool new_pass_; + unsigned short pass_; + unsigned short empty_passes_; // Number of preceding empty passes. }; } } diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx index 0586e06..2cf1a4c 100644 --- a/odb/relational/schema.cxx +++ b/odb/relational/schema.cxx @@ -6,8 +6,6 @@ #include #include -#include - #include #include @@ -17,10 +15,6 @@ namespace relational { namespace schema { - // cxx_object - // - schema_format cxx_object::format_embedded (schema_format::embedded); - void generate_prologue () { diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 2cff998..1152175 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -1488,269 +1488,6 @@ namespace relational { } }; - - // - // C++ output. - // - - struct cxx_emitter: emitter, virtual context - { - typedef cxx_emitter base; - - void - pass (unsigned short p) - { - empty_ = true; - pass_ = p; - new_pass_ = true; - - if (pass_ == 1) - empty_passes_ = 0; // New set of passes. - - // Assume this pass is empty. - // - empty_passes_++; - } - - // Did this pass produce anything? - // - bool - empty () const - { - return empty_; - } - - virtual void - pre () - { - first_ = true; - } - - virtual void - line (const string& l) - { - if (l.empty ()) - return; // Ignore empty lines. - - if (first_) - { - first_ = false; - - // If this line starts a new pass, then output the switch/case - // blocks. - // - if (new_pass_) - { - new_pass_ = false; - empty_ = false; - empty_passes_--; // This pass is not empty. - - // Output case statements for empty preceeding passes, if any. - // - if (empty_passes_ != 0) - { - unsigned short s (pass_ - empty_passes_); - - if (s == 1) - os << "switch (pass)" - << "{"; - else - os << "return true;" // One more pass. - << "}"; - - for (; s != pass_; ++s) - os << "case " << s << ":" << endl; - - os << "{"; - empty_passes_ = 0; - } - - if (pass_ == 1) - os << "switch (pass)" - << "{"; - else - os << "return true;" // One more pass. - << "}"; - - os << "case " << pass_ << ":" << endl - << "{"; - } - - os << "db.execute ("; - } - else - os << strlit (line_ + '\n') << endl; - - line_ = l; - } - - virtual void - post () - { - if (!first_) // Ignore empty statements. - os << strlit (line_) << ");"; - } - - private: - std::string line_; - bool first_; - bool empty_; - bool new_pass_; - unsigned short pass_; - unsigned short empty_passes_; // Number of preceding empty passes. - }; - - struct cxx_object: virtual context - { - typedef cxx_object base; - - //@@ (im)-perfect forwarding. - // - static schema_format format_embedded; - - cxx_object () - : stream_ (*emitter_), - drop_model_ (*emitter_, stream_, format_embedded), - drop_table_ (*emitter_, stream_, format_embedded), - create_model_ (*emitter_, stream_, format_embedded), - create_table_ (*emitter_, stream_, format_embedded) - { - init (); - } - - cxx_object (cxx_object const&) - : root_context (), //@@ -Wextra - context (), - stream_ (*emitter_), - drop_model_ (*emitter_, stream_, format_embedded), - drop_table_ (*emitter_, stream_, format_embedded), - create_model_ (*emitter_, stream_, format_embedded), - create_table_ (*emitter_, stream_, format_embedded) - { - init (); - } - - void - init () - { - drop_model_ >> drop_names_; - drop_names_ >> drop_table_; - - create_model_ >> create_names_; - create_names_ >> create_table_; - } - - void - traverse (semantics::class_& c) - { - typedef sema_rel::model::names_iterator iterator; - - iterator begin (c.get ("model-range-first")); - iterator end (c.get ("model-range-last")); - - if (begin == model->names_end ()) - return; // This class doesn't have any model entities (e.g., - // a second class mapped to the same table). - - ++end; // Transform the range from [begin, end] to [begin, end). - - string const& type (class_fq_name (c)); - string traits ("access::object_traits_impl< " + type + ", id_" + - db.string () + " >"); - - // create_schema () - // - os << "bool " << traits << "::" << endl - << "create_schema (database& db, unsigned short pass, bool drop)" - << "{" - << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (pass);" - << "ODB_POTENTIALLY_UNUSED (drop);" - << endl; - - // Drop. - // - if (!options.omit_drop ()) - { - bool close (false); - - os << "if (drop)" - << "{"; - - for (unsigned short pass (1); pass < 3; ++pass) - { - emitter_->pass (pass); - drop_model_->pass (pass); - drop_table_->pass (pass); - - drop_model_->traverse (begin, end); - - close = close || !emitter_->empty (); - } - - if (close) // Close the last case and the switch block. - os << "return false;" - << "}" // case - << "}"; // switch - - os << "}"; - } - - // Create. - // - if (!options.omit_create ()) - { - bool close (false); - - if (options.omit_drop ()) - os << "if (!drop)"; - else - os << "else"; - - os << "{"; - - for (unsigned short pass (1); pass < 3; ++pass) - { - emitter_->pass (pass); - create_model_->pass (pass); - create_table_->pass (pass); - - create_model_->traverse (begin, end); - - close = close || !emitter_->empty (); - } - - if (close) // Close the last case and the switch block. - os << "return false;" - << "}" // case - << "}"; // switch - - os << "}"; - } - - os << "return false;" - << "}"; - - os << "static const schema_catalog_entry" << endl - << "schema_catalog_entry_" << flat_name (type) << "_ (" << endl - << "id_" << db << "," << endl - << strlit (options.schema_name ()[db]) << "," << endl - << "&" << traits << "::create_schema);" - << endl; - } - - private: - instance emitter_; - emitter_ostream stream_; - - trav_rel::qnames drop_names_; - instance drop_model_; - instance drop_table_; - - trav_rel::qnames create_names_; - instance create_model_; - instance create_table_; - }; } } diff --git a/odb/relational/source.cxx b/odb/relational/source.cxx index 0eb3cd3..ceb8538 100644 --- a/odb/relational/source.cxx +++ b/odb/relational/source.cxx @@ -2911,11 +2911,6 @@ traverse_object (type& c) } } - // Generate embedded schema. - // - if (embedded_schema) - schema_->traverse (c); - // Generate function table registration for dynamic multi-database // support. // diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 22f78a7..f8987a8 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -4028,8 +4028,6 @@ namespace relational instance init_named_version_value_member_; instance init_discriminator_value_member_; instance init_named_discriminator_value_member_; - - instance schema_; }; struct include: virtual context -- cgit v1.1