From cd44a367fd73293b1c8edc36aa61667ca020a2eb Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 5 Mar 2012 11:59:00 +0200 Subject: Add support for generating schema creation code into separate C++ file --- odb/relational/generate.hxx | 6 + odb/relational/header.hxx | 2 +- odb/relational/mssql/schema.cxx | 6 +- odb/relational/oracle/schema.cxx | 12 +- odb/relational/schema-source.cxx | 44 +++++ odb/relational/schema-source.hxx | 68 ++++++++ odb/relational/schema.cxx | 8 +- odb/relational/schema.hxx | 344 +++++++++++++++++++++++++++++++++------ odb/relational/source.hxx | 224 +------------------------ 9 files changed, 430 insertions(+), 284 deletions(-) create mode 100644 odb/relational/schema-source.cxx create mode 100644 odb/relational/schema-source.hxx (limited to 'odb/relational') diff --git a/odb/relational/generate.hxx b/odb/relational/generate.hxx index 685f563..fb29bf4 100644 --- a/odb/relational/generate.hxx +++ b/odb/relational/generate.hxx @@ -29,6 +29,12 @@ namespace relational generate (); } + namespace schema_source + { + void + generate (); + } + namespace model { cutl::shared_ptr diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index dda9e2a..250a07c 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -1308,7 +1308,7 @@ namespace relational // create_schema () // - if (embedded_schema) + if (embedded_schema || separate_schema) { os << "static bool" << endl << "create_schema (database&, unsigned short pass, bool drop);" diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx index 7f50bf3..52d36ed 100644 --- a/odb/relational/mssql/schema.cxx +++ b/odb/relational/mssql/schema.cxx @@ -19,9 +19,9 @@ namespace relational { namespace relational = relational::schema; - struct schema_emitter: relational::schema_emitter + struct sql_emitter: relational::sql_emitter { - schema_emitter (const base& x): base (x) {} + sql_emitter (const base& x): base (x) {} virtual void post () @@ -34,7 +34,7 @@ namespace relational } } }; - entry schema_emitter_; + entry sql_emitter_; // // Drop. diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx index a9f5a36..2fd0602 100644 --- a/odb/relational/oracle/schema.cxx +++ b/odb/relational/oracle/schema.cxx @@ -19,9 +19,9 @@ namespace relational { namespace relational = relational::schema; - struct schema_emitter: relational::schema_emitter + struct sql_emitter: relational::sql_emitter { - schema_emitter (const base& x): base (x) {} + sql_emitter (const base& x): base (x) {} virtual void line (const std::string& l) @@ -54,15 +54,15 @@ namespace relational private: string last_; }; - entry schema_emitter_; + entry sql_emitter_; // // File. // - struct schema_file: relational::schema_file, context + struct sql_file: relational::sql_file, context { - schema_file (const base& x): base (x) {} + sql_file (const base& x): base (x) {} virtual void prologue () @@ -82,7 +82,7 @@ namespace relational os << "EXIT;" << endl; } }; - entry schema_file_; + entry sql_file_; // // Drop. diff --git a/odb/relational/schema-source.cxx b/odb/relational/schema-source.cxx new file mode 100644 index 0000000..0acb6c4 --- /dev/null +++ b/odb/relational/schema-source.cxx @@ -0,0 +1,44 @@ +// file : odb/relational/schema-source.cxx +// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#include +#include + +using namespace std; + +namespace relational +{ + namespace schema_source + { + void + generate () + { + context ctx; + ostream& os (ctx.os); + + traversal::unit unit; + traversal::defines unit_defines; + traversal::namespace_ ns; + instance c; + + unit >> unit_defines >> ns; + unit_defines >> c; + + traversal::defines ns_defines; + + ns >> ns_defines >> ns; + ns_defines >> c; + + instance i; + i->generate (); + + os << "namespace odb" + << "{"; + + unit.dispatch (ctx.unit); + + os << "}"; + } + } +} diff --git a/odb/relational/schema-source.hxx b/odb/relational/schema-source.hxx new file mode 100644 index 0000000..a72b55b --- /dev/null +++ b/odb/relational/schema-source.hxx @@ -0,0 +1,68 @@ +// file : odb/relational/schema-source.hxx +// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC +// license : GNU GPL v3; see accompanying LICENSE file + +#ifndef ODB_RELATIONAL_SCHEMA_SOURCE_HXX +#define ODB_RELATIONAL_SCHEMA_SOURCE_HXX + +#include + +#include +#include + +namespace relational +{ + namespace schema_source + { + struct class_: traversal::class_, virtual context + { + typedef class_ base; + + virtual void + traverse (type& c) + { + if (class_file (c) != unit.file () || !object (c) || abstract (c)) + return; + + context::top_object = context::cur_object = &c; + + os << "// " << class_name (c) << endl + << "//" << endl + << endl; + + schema_->traverse (c); + + context::top_object = context::cur_object = 0; + } + + private: + instance schema_; + }; + + struct include: virtual context + { + typedef include base; + + virtual void + generate () + { + extra_pre (); + os << "#include " << endl; + extra_post (); + os << endl; + } + + virtual void + extra_pre () + { + } + + virtual void + extra_post () + { + } + }; + } +} + +#endif // ODB_RELATIONAL_SCHEMA_SOURCE_HXX diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx index 05f5949..ea9083d 100644 --- a/odb/relational/schema.cxx +++ b/odb/relational/schema.cxx @@ -17,6 +17,10 @@ namespace relational { namespace schema { + // cxx_object + // + schema_format cxx_object::format_embedded (schema_format::embedded); + static char const file_header[] = "/* This file was generated by ODB, object-relational mapping (ORM)\n" " * compiler for C++.\n" @@ -30,10 +34,10 @@ namespace relational os << file_header; - instance file; + instance file; file->prologue (); - instance em; + instance em; emitter_ostream emos (*em); schema_format f (schema_format::sql); diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 7e8d34c..b0ac01f 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -54,58 +54,6 @@ namespace relational ostream& os_; }; - struct schema_emitter: emitter, virtual context - { - typedef schema_emitter base; - - virtual void - pre () - { - first_ = true; - } - - virtual void - line (const std::string& l) - { - if (first_ && !l.empty ()) - first_ = false; - else - os << endl; - - os << l; - } - - virtual void - post () - { - if (!first_) // Ignore empty statements. - os << ';' << endl - << endl; - } - - protected: - bool first_; - }; - - // - // File prologue/epilogue. - // - - struct schema_file: virtual context - { - typedef schema_file base; - - virtual void - prologue () - { - } - - virtual void - epilogue () - { - } - }; - // // Drop. // @@ -675,6 +623,298 @@ namespace relational schema_format format_; unsigned short pass_; }; + + // + // SQL output. + // + + struct sql_emitter: emitter, virtual context + { + typedef sql_emitter base; + + virtual void + pre () + { + first_ = true; + } + + virtual void + line (const std::string& l) + { + if (first_ && !l.empty ()) + first_ = false; + else + os << endl; + + os << l; + } + + virtual void + post () + { + if (!first_) // Ignore empty statements. + os << ';' << endl + << endl; + } + + protected: + bool first_; + }; + + struct sql_file: virtual context + { + typedef sql_file base; + + virtual void + prologue () + { + } + + virtual void + epilogue () + { + } + }; + + // + // C++ output. + // + + struct cxx_emitter: emitter, virtual context + { + typedef cxx_emitter base; + + void + pass (unsigned short p) + { + empty_ = true; + pass_ = p; + new_pass_ = true; + } + + // 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; + + if (pass_ == 1) + { + os << "switch (pass)" + << "{" + << "case 1:" << endl + << "{"; + } + else + { + os << "return true;" // One more pass. + << "}" + << "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_) << ");" << endl; + } + + private: + std::string line_; + bool first_; + bool empty_; + bool new_pass_; + unsigned short pass_; + }; + + 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), + drop_index_ (*emitter_, stream_, format_embedded), + create_model_ (*emitter_, stream_, format_embedded), + create_table_ (*emitter_, stream_, format_embedded), + create_index_ (*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), + drop_index_ (*emitter_, stream_, format_embedded), + create_model_ (*emitter_, stream_, format_embedded), + create_table_ (*emitter_, stream_, format_embedded), + create_index_ (*emitter_, stream_, format_embedded) + { + init (); + } + + void + init () + { + drop_model_ >> drop_names_; + drop_names_ >> drop_table_; + drop_names_ >> drop_index_; + + create_model_ >> create_names_; + create_names_ >> create_table_; + create_names_ >> create_index_; + } + + 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< " + type + " >"); + + // create_schema () + // + os << "bool " << traits << "::" << endl + << "create_schema (database& db, unsigned short pass, bool drop)" + << "{" + << "ODB_POTENTIALLY_UNUSED (db);" + << "ODB_POTENTIALLY_UNUSED (pass);" + << endl; + + // 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_index_->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. + // + { + bool close (false); + + os << "else" + << "{"; + + for (unsigned short pass (1); pass < 3; ++pass) + { + emitter_->pass (pass); + create_model_->pass (pass); + create_table_->pass (pass); + create_index_->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 + << strlit (options.schema_name ()) << "," << endl + << "&" << traits << "::create_schema);" + << endl; + } + + private: + instance emitter_; + emitter_ostream stream_; + + trav_rel::qnames drop_names_; + instance drop_model_; + instance drop_table_; + instance drop_index_; + + trav_rel::qnames create_names_; + instance create_model_; + instance create_table_; + instance create_index_; + }; } } diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index ab5220a..fb13ade 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -2665,10 +2664,6 @@ namespace relational query_parameters& qp_; }; - //@@ (im)-perfect forwarding. - // - static schema_format format_embedded (schema_format::embedded); - // // struct class_: traversal::class_, virtual context @@ -2683,14 +2678,7 @@ namespace relational init_id_image_member_ ("id_", "id"), init_version_image_member_ ("version_", "(*v)"), init_id_value_member_ ("id"), - init_version_value_member_ ("v"), - stream_ (emitter_), - drop_model_ (emitter_, stream_, format_embedded), - drop_table_ (emitter_, stream_, format_embedded), - drop_index_ (emitter_, stream_, format_embedded), - create_model_ (emitter_, stream_, format_embedded), - create_table_ (emitter_, stream_, format_embedded), - create_index_ (emitter_, stream_, format_embedded) + init_version_value_member_ ("v") { init (); } @@ -2705,14 +2693,7 @@ namespace relational init_id_image_member_ ("id_", "id"), init_version_image_member_ ("version_", "(*v)"), init_id_value_member_ ("id"), - init_version_value_member_ ("v"), - stream_ (emitter_), - drop_model_ (emitter_, stream_, format_embedded), - drop_table_ (emitter_, stream_, format_embedded), - drop_index_ (emitter_, stream_, format_embedded), - create_model_ (emitter_, stream_, format_embedded), - create_table_ (emitter_, stream_, format_embedded), - create_index_ (emitter_, stream_, format_embedded) + init_version_value_member_ ("v") { init (); } @@ -2734,17 +2715,6 @@ namespace relational init_value_base_inherits_ >> init_value_base_; init_value_member_names_ >> init_value_member_; - - if (embedded_schema) - { - drop_model_ >> drop_names_; - drop_names_ >> drop_table_; - drop_names_ >> drop_index_; - - create_model_ >> create_names_; - create_names_ >> create_table_; - create_names_ >> create_index_; - } } virtual void @@ -4016,180 +3986,7 @@ namespace relational } if (embedded_schema) - schema (c); - } - - struct schema_emitter: emitter, virtual context - { - void - pass (unsigned short p) - { - empty_ = true; - pass_ = p; - new_pass_ = true; - } - - // 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; - - if (pass_ == 1) - { - os << "switch (pass)" - << "{" - << "case 1:" << endl - << "{"; - } - else - { - os << "return true;" // One more pass. - << "}" - << "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_) << ");" << endl; - } - - private: - std::string line_; - bool first_; - bool empty_; - bool new_pass_; - unsigned short pass_; - }; - - virtual void - schema (type& 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< " + type + " >"); - - // create_schema () - // - os << "bool " << traits << "::" << endl - << "create_schema (database& db, unsigned short pass, bool drop)" - << "{" - << "ODB_POTENTIALLY_UNUSED (db);" - << "ODB_POTENTIALLY_UNUSED (pass);" - << endl; - - // 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_index_->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. - // - { - bool close (false); - - os << "else" - << "{"; - - for (unsigned short pass (1); pass < 3; ++pass) - { - emitter_.pass (pass); - create_model_->pass (pass); - create_table_->pass (pass); - create_index_->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 - << strlit (options.schema_name ()) << "," << endl - << "&" << traits << "::create_schema);" - << endl; + schema_->traverse (c); } // @@ -5120,9 +4917,7 @@ namespace relational } private: - bool id_; size_t index_; - instance grow_base_; traversal::inherits grow_base_inherits_; instance grow_member_; @@ -5151,18 +4946,7 @@ namespace relational instance init_id_value_member_; instance init_version_value_member_; - schema_emitter emitter_; - emitter_ostream stream_; - - trav_rel::qnames drop_names_; - instance drop_model_; - instance drop_table_; - instance drop_index_; - - trav_rel::qnames create_names_; - instance create_model_; - instance create_table_; - instance create_index_; + instance schema_; }; struct include: virtual context -- cgit v1.1