aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-09 10:03:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-10 18:46:45 +0200
commit5ebd62ec778bc8c9540e2379e764ac52c060adfc (patch)
treeb751e62fe12599ee1a2553dc9331a03c8c957252
parent8295d4bd02946b7bdbff2a9cfa7763232e2d2fd0 (diff)
Generate embedded schema in single function instead of one per object
-rw-r--r--odb/generator.cxx12
-rw-r--r--odb/relational/generate.hxx11
-rw-r--r--odb/relational/header.cxx9
-rw-r--r--odb/relational/model.hxx11
-rw-r--r--odb/relational/schema-source.cxx114
-rw-r--r--odb/relational/schema-source.hxx119
-rw-r--r--odb/relational/schema.cxx6
-rw-r--r--odb/relational/schema.hxx263
-rw-r--r--odb/relational/source.cxx5
-rw-r--r--odb/relational/source.hxx2
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 <odb/database.hxx>" << endl
+ << "#include <odb/schema-catalog-impl.hxx>" << endl
+ << endl
+ << "#include <odb/details/unused.hxx>" << 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<semantics::relational::model>
@@ -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<sema_rel::qnames> (model_, t, name);
- sema_rel::model::names_iterator begin (--model_.names_end ());
-
// Add columns.
//
{
@@ -731,11 +725,6 @@ namespace relational
instance<member_create> 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<class_> c;
+ instance<cxx_emitter> 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<include> i;
- i->generate ();
+ instance<drop_model> dmodel (*emitter, emitter_os, format);
+ instance<drop_table> 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<create_model> cmodel (*emitter, emitter_os, format);
+ instance<create_table> 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 <odb/diagnostics.hxx>
+#include <odb/emitter.hxx>
#include <odb/relational/context.hxx>
#include <odb/relational/schema.hxx>
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::cxx_object> 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 <odb/schema-catalog-impl.hxx>" << 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 <limits>
#include <sstream>
-#include <odb/emitter.hxx>
-
#include <odb/relational/schema.hxx>
#include <odb/relational/generate.hxx>
@@ -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<iterator> ("model-range-first"));
- iterator end (c.get<iterator> ("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<cxx_emitter> emitter_;
- emitter_ostream stream_;
-
- trav_rel::qnames drop_names_;
- instance<drop_model> drop_model_;
- instance<drop_table> drop_table_;
-
- trav_rel::qnames create_names_;
- instance<create_model> create_model_;
- instance<create_table> 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_value_member> init_named_version_value_member_;
instance<init_value_member> init_discriminator_value_member_;
instance<init_value_member> init_named_discriminator_value_member_;
-
- instance<schema::cxx_object> schema_;
};
struct include: virtual context