aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--doc/manual.xhtml20
-rw-r--r--doc/odb-prologue.17
-rw-r--r--doc/odb-prologue.xhtml5
-rw-r--r--odb/context.cxx3
-rw-r--r--odb/context.hxx1
-rw-r--r--odb/generator.cxx76
-rw-r--r--odb/makefile3
-rw-r--r--odb/option-types.cxx1
-rw-r--r--odb/option-types.hxx1
-rw-r--r--odb/options.cli42
-rw-r--r--odb/relational/generate.hxx6
-rw-r--r--odb/relational/header.hxx2
-rw-r--r--odb/relational/mssql/schema.cxx6
-rw-r--r--odb/relational/oracle/schema.cxx12
-rw-r--r--odb/relational/schema-source.cxx44
-rw-r--r--odb/relational/schema-source.hxx68
-rw-r--r--odb/relational/schema.cxx8
-rw-r--r--odb/relational/schema.hxx344
-rw-r--r--odb/relational/source.hxx224
20 files changed, 580 insertions, 299 deletions
diff --git a/NEWS b/NEWS
index f2ec0fd..890eae2 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,12 @@ Version 1.9.0
7.2.1, "Composite Object Ids" in the ODB manual as well as the 'composite'
example in the odb-examples package.
+ * New schema format (--schema-format), 'separate', allows the generation
+ of the schema creation code into a separate C++ source file (called
+ 'name-schema.cxx' by default). This value is primarily useful if you
+ want to place the schema creation functionality into a separate program
+ or library.
+
Version 1.8.0
* Support for the Microsoft SQL Server database. The provided connection
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index 347c8ef..5060268 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -2394,16 +2394,16 @@ auto_ptr<odb::database> db (
<p>There are several ways to create the database schema. The easiest is to
instruct the ODB compiler to generate the corresponding schema from the
persistent classes (<code>--generate-schema</code> option). The ODB
- compiler can generate the schema either as a standalone SQL file or
- embedded into the generated C++ code (<code>--schema-format</code>
- option). If we are using the SQL file to create the database schema, then
- this file should be executed, normally only once, before the application
- is started.</p>
-
- <p>Alternatively, the schema can be embedded directly into the generated
- code and we can use the <code>odb::schema_catalog</code> class to
- create it in the database from within our application,
- for example:</p>
+ compiler can generate the schema as a standalone SQL file,
+ embedded into the generated C++ code, or as a separate C++ source file
+ (<code>--schema-format</code> option). If we are using the SQL file
+ to create the database schema, then this file should be executed,
+ normally only once, before the application is started.</p>
+
+ <p>Alternatively, if the schema is embedded directly into the generated
+ code or produced as a separate C++ source file, then we can use the
+ <code>odb::schema_catalog</code> class to create it in the database
+ from within our application, for example:</p>
<pre class="c++">
#include &lt;odb/schema-catalog.hxx>
diff --git a/doc/odb-prologue.1 b/doc/odb-prologue.1
index ca9d079..78d95c4 100644
--- a/doc/odb-prologue.1
+++ b/doc/odb-prologue.1
@@ -53,7 +53,12 @@ option is specified and the
.B sql
schema format is requested, the
.B name.sql
-database schema file is generated.
+database schema file is generated. If the
+.B separate
+schema format is requested, the database creation code is generated into
+the separate
+.B name-schema.cxx
+file.
.\"
.\"
.\"
diff --git a/doc/odb-prologue.xhtml b/doc/odb-prologue.xhtml
index 79a06eb..46d6e3f 100644
--- a/doc/odb-prologue.xhtml
+++ b/doc/odb-prologue.xhtml
@@ -75,6 +75,9 @@
Additionally, if the <code><b>--generate-schema</b></code> option is
specified and the <code><b>sql</b></code> schema format is requested,
- the <code><b>name.sql</b></code> database schema file is generated.</p>
+ the <code><b>name.sql</b></code> database schema file is generated. If
+ the <code><b>separate</b></code> schema format is requested, the database
+ creation code is generated into the separate
+ <code><b>name-schema.cxx</b></code> file.</p>
<h1>OPTIONS</h1>
diff --git a/odb/context.cxx b/odb/context.cxx
index 86cca9d..265d4ca 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -179,6 +179,8 @@ context (ostream& os_,
include_regex (data_->include_regex_),
embedded_schema (ops.generate_schema () &&
ops.schema_format ().count (schema_format::embedded)),
+ separate_schema (ops.generate_schema () &&
+ ops.schema_format ().count (schema_format::separate)),
top_object (data_->top_object_),
cur_object (data_->cur_object_)
{
@@ -203,6 +205,7 @@ context ()
keyword_set (current ().keyword_set),
include_regex (current ().include_regex),
embedded_schema (current ().embedded_schema),
+ separate_schema (current ().separate_schema),
top_object (current ().top_object),
cur_object (current ().cur_object)
{
diff --git a/odb/context.hxx b/odb/context.hxx
index 3865e88..b590ea4 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -818,6 +818,7 @@ public:
regex_mapping const& include_regex;
bool embedded_schema;
+ bool separate_schema;
// Outermost object or view currently being traversed.
//
diff --git a/odb/generator.cxx b/odb/generator.cxx
index bd5c9d5..2ab272d 100644
--- a/odb/generator.cxx
+++ b/odb/generator.cxx
@@ -123,11 +123,13 @@ generate (options const& ops, semantics::unit& unit, path const& p)
string hxx_name (base + ops.odb_file_suffix () + ops.hxx_suffix ());
string ixx_name (base + ops.odb_file_suffix () + ops.ixx_suffix ());
string cxx_name (base + ops.odb_file_suffix () + ops.cxx_suffix ());
+ string sch_name (base + ops.schema_file_suffix () + ops.cxx_suffix ());
string sql_name (base + ops.sql_suffix ());
path hxx_path (hxx_name);
path ixx_path (ixx_name);
path cxx_path (cxx_name);
+ path sch_path (sch_name);
path sql_path (sql_name);
if (!ops.output_dir ().empty ())
@@ -136,6 +138,7 @@ generate (options const& ops, semantics::unit& unit, path const& p)
hxx_path = dir / hxx_path;
ixx_path = dir / ixx_path;
cxx_path = dir / cxx_path;
+ sch_path = dir / sch_path;
sql_path = dir / sql_path;
}
@@ -198,12 +201,36 @@ generate (options const& ops, semantics::unit& unit, path const& p)
auto_rm.add (sql_path);
}
+ //
+ //
+ bool sep_schema (ops.generate_schema () &&
+ ops.schema_format ().count (schema_format::separate));
+
+ ofstream sch;
+
+ if (sep_schema)
+ {
+ sch.open (sch_path.string ().c_str (), ios_base::out);
+
+ if (!sch.is_open ())
+ {
+ cerr << "error: unable to open '" << sch_path << "' in write mode"
+ << endl;
+ throw failed ();
+ }
+
+ auto_rm.add (sch_path);
+ }
+
// Print C++ headers.
//
hxx << file_header;
ixx << file_header;
cxx << file_header;
+ if (sep_schema)
+ sch << file_header;
+
typedef compiler::ostream_filter<compiler::cxx_indenter, char> cxx_filter;
// Include settings.
@@ -367,6 +394,55 @@ generate (options const& ops, semantics::unit& unit, path const& p)
cxx << "#include <odb/post.hxx>" << endl;
}
+ // SCH
+ //
+ if (sep_schema)
+ {
+ cxx_filter filt (sch);
+ auto_ptr<context> ctx (create_context (sch, unit, ops, model.get ()));
+
+ // Copy prologue.
+ //
+ sch << "#include <odb/pre.hxx>" << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ sch << "// Begin prologue." << endl
+ << "//" << endl;
+ append (sch, ops.schema_prologue (), ops.schema_prologue_file ());
+ sch << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ sch << "#include " << ctx->process_include_path (hxx_name) << endl
+ << endl;
+
+ switch (ops.database ())
+ {
+ case database::mssql:
+ case database::mysql:
+ case database::oracle:
+ case database::pgsql:
+ case database::sqlite:
+ {
+ relational::schema_source::generate ();
+ break;
+ }
+ }
+
+ // Copy epilogue.
+ //
+ sch << "// Begin epilogue." << endl
+ << "//" << endl;
+ append (sch, ops.schema_epilogue (), ops.schema_epilogue_file ());
+ sch << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ sch << "#include <odb/post.hxx>" << endl;
+ }
+
// SQL
//
if (sql_schema)
diff --git a/odb/makefile b/odb/makefile
index 244c302..d048065 100644
--- a/odb/makefile
+++ b/odb/makefile
@@ -35,7 +35,8 @@ relational/header.cxx \
relational/inline.cxx \
relational/source.cxx \
relational/model.cxx \
-relational/schema.cxx
+relational/schema.cxx \
+relational/schema-source.cxx
# Relational/MSSQL.
#
diff --git a/odb/option-types.cxx b/odb/option-types.cxx
index 3bbe72e..ceb71db 100644
--- a/odb/option-types.cxx
+++ b/odb/option-types.cxx
@@ -98,6 +98,7 @@ operator<< (ostream& os, database db)
static const char* schema_format_[] =
{
"embedded",
+ "separate",
"sql"
};
diff --git a/odb/option-types.hxx b/odb/option-types.hxx
index de3bdb7..66e2f28 100644
--- a/odb/option-types.hxx
+++ b/odb/option-types.hxx
@@ -72,6 +72,7 @@ struct schema_format
// Keep in alphabetic order.
//
embedded,
+ separate,
sql
};
diff --git a/odb/options.cli b/odb/options.cli
index f501315..ae72e25 100644
--- a/odb/options.cli
+++ b/odb/options.cli
@@ -79,6 +79,10 @@ class options
"Generate the database schema in the specified format. Pass \cb{sql} as
<format> to generate the database schema as a standalone SQL file or
pass \cb{embedded} to embed the schema into the generated C++ code.
+ The \cb{separate} value is similar to \cb{embedded} except the schema
+ creation code is generated into a separate C++ file (\cb{name-schema.cxx}
+ by default). This value is primarily useful if you want to place the
+ schema creation functionality into a separate program or library.
Repeat this option to generate the same database schema in multiple
formats."
};
@@ -188,6 +192,14 @@ class options
of the generated C++ files."
};
+ std::string --schema-file-suffix = "-schema"
+ {
+ "<suffix>",
+ "Use <suffix> instead of the default \cb{-schema} to construct the name
+ of the generated schema C++ source file. See the \cb{--schema-format}
+ option for details."
+ };
+
std::string --hxx-suffix = ".hxx"
{
"<suffix>",
@@ -236,6 +248,12 @@ class options
"Insert <text> at the beginning of the generated C++ source file."
};
+ std::vector<std::string> --schema-prologue
+ {
+ "<text>",
+ "Insert <text> at the beginning of the generated schema C++ source file."
+ };
+
std::vector<std::string> --sql-prologue
{
"<text>",
@@ -262,6 +280,12 @@ class options
"Insert <text> at the end of the generated C++ source file."
};
+ std::vector<std::string> --schema-epilogue
+ {
+ "<text>",
+ "Insert <text> at the end of the generated schema C++ source file."
+ };
+
std::vector<std::string> --sql-epilogue
{
"<text>",
@@ -291,6 +315,13 @@ class options
source file."
};
+ std::string --schema-prologue-file
+ {
+ "<file>",
+ "Insert the content of <file> at the beginning of the generated schema
+ C++ source file."
+ };
+
std::string --sql-prologue-file
{
"<file>",
@@ -321,6 +352,13 @@ class options
file."
};
+ std::string --schema-epilogue-file
+ {
+ "<file>",
+ "Insert the content of <file> at the end of the generated schema C++
+ source file."
+ };
+
std::string --sql-epilogue-file
{
"<file>",
@@ -454,7 +492,7 @@ class options
::mssql_version --mssql-server-version (10, 0)
{
- "<v>",
+ "<ver>",
"Specify the minimum SQL Server server version with which the generated
C++ code will be used. This information is used to enable
version-specific optimizations and workarounds in the generated C++
@@ -502,7 +540,7 @@ class options
::oracle_version --oracle-client-version (10, 1)
{
- "<v>",
+ "<ver>",
"Specify the minimum Oracle client library (OCI) version with which the
generated C++ code will be linked. This information is used to enable
version-specific optimizations and workarounds in the generated C++
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<semantics::relational::model>
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> schema_emitter_;
+ entry<sql_emitter> 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> schema_emitter_;
+ entry<sql_emitter> 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> schema_file_;
+ entry<sql_file> 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 <odb/relational/schema-source.hxx>
+#include <odb/relational/generate.hxx>
+
+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<class_> c;
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+
+ traversal::defines ns_defines;
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+
+ instance<include> 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 <odb/diagnostics.hxx>
+
+#include <odb/relational/context.hxx>
+#include <odb/relational/schema.hxx>
+
+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::cxx_object> schema_;
+ };
+
+ struct include: virtual context
+ {
+ typedef include base;
+
+ virtual void
+ generate ()
+ {
+ extra_pre ();
+ os << "#include <odb/schema-catalog-impl.hxx>" << 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<schema_file> file;
+ instance<sql_file> file;
file->prologue ();
- instance<schema_emitter> em;
+ instance<sql_emitter> 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<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< " + 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<cxx_emitter> emitter_;
+ emitter_ostream stream_;
+
+ trav_rel::qnames drop_names_;
+ instance<drop_model> drop_model_;
+ instance<drop_table> drop_table_;
+ instance<drop_index> drop_index_;
+
+ trav_rel::qnames create_names_;
+ instance<create_model> create_model_;
+ instance<create_table> create_table_;
+ instance<create_index> 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 <sstream>
#include <odb/diagnostics.hxx>
-#include <odb/emitter.hxx>
#include <odb/relational/context.hxx>
#include <odb/relational/common.hxx>
@@ -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<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< " + 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> grow_base_;
traversal::inherits grow_base_inherits_;
instance<grow_member> grow_member_;
@@ -5151,18 +4946,7 @@ namespace relational
instance<init_value_member> init_id_value_member_;
instance<init_value_member> init_version_value_member_;
- schema_emitter emitter_;
- emitter_ostream stream_;
-
- trav_rel::qnames drop_names_;
- instance<schema::drop_model> drop_model_;
- instance<schema::drop_table> drop_table_;
- instance<schema::drop_index> drop_index_;
-
- trav_rel::qnames create_names_;
- instance<schema::create_model> create_model_;
- instance<schema::create_table> create_table_;
- instance<schema::create_index> create_index_;
+ instance<schema::cxx_object> schema_;
};
struct include: virtual context