summaryrefslogtreecommitdiff
path: root/odb/relational/mysql
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-08 14:22:00 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-10 18:46:44 +0200
commita9da959e71ce02b7e8b0457edcae303043b2799a (patch)
tree6ad504022ce8b6e841891b40820519d1c1311205 /odb/relational/mysql
parent104cdccab69dd0b68a756f5d54126a6b74914408 (diff)
Use single ALTER TABLE to add foreign keys on pass 2
Diffstat (limited to 'odb/relational/mysql')
-rw-r--r--odb/relational/mysql/schema.cxx96
1 files changed, 66 insertions, 30 deletions
diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx
index be058ce..d1721fa 100644
--- a/odb/relational/mysql/schema.cxx
+++ b/odb/relational/mysql/schema.cxx
@@ -130,14 +130,14 @@ namespace relational
create_foreign_key (base const& x): base (x) {}
virtual void
- generate (sema_rel::foreign_key& fk)
+ traverse_create (sema_rel::foreign_key& fk)
{
// MySQL does not support deferrable constraint checking. Output
// such foreign keys as comments, for documentation, unless we
// are generating embedded schema.
//
if (fk.not_deferrable ())
- base::generate (fk);
+ base::traverse_create (fk);
else
{
// Don't bloat C++ code with comment strings if we are
@@ -149,17 +149,17 @@ namespace relational
os << endl
<< " /*" << endl
<< " CONSTRAINT ";
- base::create (fk);
+ create (fk);
os << endl
<< " */";
}
}
virtual void
- traverse (sema_rel::add_foreign_key& afk)
+ traverse_add (sema_rel::foreign_key& fk)
{
- if (afk.not_deferrable () || in_comment)
- base::traverse (afk);
+ if (fk.not_deferrable () || in_comment)
+ base::traverse_add (fk);
else
{
if (format_ != schema_format::sql)
@@ -169,7 +169,7 @@ namespace relational
<< " /*"
<< endl;
- add (afk);
+ add (fk);
os << endl
<< " */";
@@ -184,37 +184,73 @@ namespace relational
};
entry<create_foreign_key> create_foreign_key_;
- struct add_foreign_key: relational::add_foreign_key, context
+ struct create_table: relational::create_table, context
{
- add_foreign_key (base const& x): base (x) {}
+ create_table (base const& x): base (x) {}
- virtual void
- generate (sema_rel::table& t, sema_rel::foreign_key& fk)
+ // See if there are any undefined foreign keys that are not
+ // deferrable.
+ //
+ bool
+ check_undefined_fk_deferrable_only (sema_rel::table& t)
{
- // MySQL has no deferrable constraints.
- //
- if (fk.not_deferrable ())
- base::generate (t, fk);
- else
+ for (sema_rel::table::names_iterator i (t.names_begin ());
+ i != t.names_end (); ++i)
{
- if (format_ != schema_format::sql)
- return;
+ using sema_rel::foreign_key;
- os << "/*" << endl;
- os << "ALTER TABLE " << quote_id (t.name ()) << endl
- << " ADD CONSTRAINT ";
- def_->create (fk);
- os << endl
- << "*/" << endl
- << endl;
+ if (foreign_key* fk = dynamic_cast<foreign_key*> (&i->nameable ()))
+ {
+ if (!fk->count ("mysql-fk-defined") &&
+ fk->not_deferrable ())
+ return false;
+ }
}
+ return true;
}
- };
- entry<add_foreign_key> add_foreign_key_;
- struct create_table: relational::create_table, context
- {
- create_table (base const& x): base (x) {}
+ virtual void
+ traverse (sema_rel::table& t)
+ {
+ if (pass_ == 1)
+ base::traverse (t);
+ else
+ {
+ // Add undefined foreign keys.
+ //
+ if (check_undefined_fk (t))
+ {
+ bool deferrable (check_undefined_fk_deferrable_only (t));
+
+ if (!deferrable || format_ == schema_format::sql)
+ {
+ if (deferrable)
+ {
+ os << "/*" << endl;
+ in_comment = true;
+ }
+ else
+ pre_statement ();
+
+ os << "ALTER TABLE " << quote_id (t.name ());
+
+ instance<create_foreign_key> cfk (*this);
+ trav_rel::unames n (*cfk);
+ names (t, n);
+ os << endl;
+
+ if (deferrable)
+ {
+ in_comment = false;
+ os << "*/" << endl
+ << endl;
+ }
+ else
+ post_statement ();
+ }
+ }
+ }
+ }
virtual void
create_post ()