aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-04-04 09:47:32 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-10 18:46:44 +0200
commit6d4b471afd63780b8a8a6c2d3fb8cc529ab5b15d (patch)
treed4cf0158f1b2ac03736b662003dbd11b556babef
parentb0391e168b489811708ca7ba5f71a0eb67b46ffe (diff)
Generate add/drop index migration statements
-rw-r--r--odb/relational/mssql/schema.cxx15
-rw-r--r--odb/relational/mysql/schema.cxx15
-rw-r--r--odb/relational/oracle/schema.cxx19
-rw-r--r--odb/relational/schema.cxx18
-rw-r--r--odb/relational/schema.hxx216
-rw-r--r--odb/relational/sqlite/schema.cxx18
6 files changed, 275 insertions, 26 deletions
diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx
index 11467b3..58c0206 100644
--- a/odb/relational/mssql/schema.cxx
+++ b/odb/relational/mssql/schema.cxx
@@ -290,6 +290,21 @@ namespace relational
trav_rel::unames n (fk);
names (t, n);
}
+
+ struct drop_index: relational::drop_index, context
+ {
+ drop_index (base const& x): base (x) {}
+
+ virtual void
+ drop (sema_rel::index& in)
+ {
+ sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
+
+ os << "DROP INDEX " << name (in) << " ON " <<
+ quote_id (t.name ()) << endl;
+ }
+ };
+ entry<drop_index> drop_index_;
}
}
}
diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx
index e216918..c3f7571 100644
--- a/odb/relational/mysql/schema.cxx
+++ b/odb/relational/mysql/schema.cxx
@@ -352,6 +352,21 @@ namespace relational
}
};
entry<create_index> create_index_;
+
+ struct drop_index: relational::drop_index, context
+ {
+ drop_index (base const& x): base (x) {}
+
+ virtual void
+ drop (sema_rel::index& in)
+ {
+ sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
+
+ os << "DROP INDEX " << name (in) << " ON " <<
+ quote_id (t.name ()) << endl;
+ }
+ };
+ entry<drop_index> drop_index_;
}
}
}
diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx
index bd0acda..a76e25a 100644
--- a/odb/relational/oracle/schema.cxx
+++ b/odb/relational/oracle/schema.cxx
@@ -95,7 +95,7 @@ namespace relational
virtual void
traverse (sema_rel::table& t, bool migration)
{
- if (pass_ != 1)
+ if (pass_ != 2)
return;
using sema_rel::primary_key;
@@ -290,6 +290,23 @@ namespace relational
}
};
entry<create_index> create_index_;
+
+ struct drop_index: relational::drop_index, context
+ {
+ drop_index (base const& x): base (x) {}
+
+ virtual string
+ name (sema_rel::index& in)
+ {
+ // In Oracle, index names can be qualified with the schema.
+ //
+ sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
+ sema_rel::qname n (t.name ().qualifier ());
+ n.append (in.name ());
+ return quote_id (n);
+ }
+ };
+ entry<drop_index> drop_index_;
}
}
}
diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx
index e764790..56fb7c0 100644
--- a/odb/relational/schema.cxx
+++ b/odb/relational/schema.cxx
@@ -96,11 +96,14 @@ namespace relational
schema_format f (schema_format::sql);
- instance<migrate_pre_changeset> changeset (*em, emos, f);
+ instance<changeset_pre> changeset (*em, emos, f);
instance<create_table> ctable (*em, emos, f);
+ instance<alter_table_pre> atable (*em, emos, f);
trav_rel::qnames names;
- changeset >> names >> ctable;
+ changeset >> names;
+ names >> ctable;
+ names >> atable;
// Pass 1 and 2.
//
@@ -108,6 +111,7 @@ namespace relational
{
changeset->pass (pass);
ctable->pass (pass);
+ atable->pass (pass);
changeset->traverse (cs);
}
@@ -122,11 +126,16 @@ namespace relational
schema_format f (schema_format::sql);
- instance<migrate_post_changeset> changeset (*em, emos, f);
+ instance<changeset_post> changeset (*em, emos, f);
instance<drop_table> dtable (*em, emos, f);
+ instance<alter_table_post> altable (*em, emos, f);
+ trav_rel::add_table adtable; // Override.
trav_rel::qnames names;
- changeset >> names >> dtable;
+ changeset >> names;
+ names >> dtable;
+ names >> altable;
+ names >> adtable;
// Pass 1 and 2.
//
@@ -134,6 +143,7 @@ namespace relational
{
changeset->pass (pass);
dtable->pass (pass);
+ altable->pass (pass);
changeset->traverse (cs);
}
diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx
index 8ce9f59..5d3d91f 100644
--- a/odb/relational/schema.hxx
+++ b/odb/relational/schema.hxx
@@ -58,10 +58,80 @@ namespace relational
// Drop.
//
+ // Currently only used in migration.
+ //
+ struct drop_index: trav_rel::drop_index, common
+ {
+ typedef drop_index base;
+
+ enum index_type {unique, non_unique, all};
+
+ drop_index (emitter_type& e,
+ ostream& os,
+ schema_format f,
+ index_type t = all)
+ : common (e, os), format_ (f), type_ (t)
+ {
+ }
+
+ virtual void
+ traverse (sema_rel::drop_index& di)
+ {
+ using sema_rel::model;
+ using sema_rel::changeset;
+ using sema_rel::table;
+ using sema_rel::alter_table;
+ using sema_rel::index;
+
+ // Find the index we are dropping in the base model.
+ //
+ alter_table& at (dynamic_cast<alter_table&> (di.scope ()));
+ changeset& cs (dynamic_cast<changeset&> (at.scope ()));
+ model& bm (cs.base_model ());
+ table* bt (bm.find<table> (at.name ()));
+ assert (bt != 0);
+ index* bi (bt->find<index> (di.name ()));
+ assert (bi != 0);
+ traverse (*bi);
+ }
+
+ virtual void
+ traverse (sema_rel::index& in)
+ {
+ if (type_ == unique &&
+ in.type ().find ("UNIQUE") == string::npos &&
+ in.type ().find ("unique") == string::npos)
+ return;
+
+ if (type_ == non_unique && (
+ in.type ().find ("UNIQUE") != string::npos ||
+ in.type ().find ("unique") != string::npos))
+ return;
+
+ pre_statement ();
+ drop (in);
+ post_statement ();
+ }
+
+ virtual string
+ name (sema_rel::index& in)
+ {
+ return quote_id (in.name ());
+ }
+
+ virtual void
+ drop (sema_rel::index& in)
+ {
+ os << "DROP INDEX " << name (in) << endl;
+ }
+
+ protected:
+ schema_format format_;
+ index_type type_;
+ };
+
struct drop_table: trav_rel::table,
trav_rel::drop_table,
- trav_rel::add_table, // override
- trav_rel::alter_table, // override
common
{
typedef drop_table base;
@@ -81,10 +151,10 @@ namespace relational
virtual void
traverse (sema_rel::table& t, bool migration)
{
- // By default we do everything in a single pass. But some
- // databases may require the second pass.
+ // By default we do everything in a single, last pass. But some
+ // databases may require two passes.
//
- if (pass_ > 1)
+ if (pass_ != 2)
return;
pre_statement ();
@@ -114,12 +184,6 @@ namespace relational
traverse (*t, true);
}
- virtual void
- traverse (sema_rel::add_table&) {}
-
- virtual void
- traverse (sema_rel::alter_table&) {}
-
using table::names;
void
@@ -453,14 +517,29 @@ namespace relational
{
typedef create_index base;
- create_index (emitter_type& e, ostream& os, schema_format f)
- : common (e, os), format_ (f)
+ enum index_type {unique, non_unique, all};
+
+ create_index (emitter_type& e,
+ ostream& os,
+ schema_format f,
+ index_type t = all)
+ : common (e, os), format_ (f), type_ (t)
{
}
virtual void
traverse (sema_rel::index& in)
{
+ if (type_ == unique &&
+ in.type ().find ("UNIQUE") == string::npos &&
+ in.type ().find ("unique") == string::npos)
+ return;
+
+ if (type_ == non_unique && (
+ in.type ().find ("UNIQUE") != string::npos ||
+ in.type ().find ("unique") != string::npos))
+ return;
+
pre_statement ();
create (in);
post_statement ();
@@ -526,6 +605,7 @@ namespace relational
protected:
schema_format format_;
+ index_type type_;
};
struct create_table: trav_rel::table, common
@@ -555,7 +635,7 @@ namespace relational
// By default we do everything in a single pass. But some
// databases may require the second pass.
//
- if (pass_ > 1)
+ if (pass_ != 1)
return;
pre_statement ();
@@ -631,11 +711,60 @@ namespace relational
unsigned short pass_;
};
- struct migrate_pre_changeset: trav_rel::changeset, common
+ // Migration.
+ //
+ struct alter_table_pre: trav_rel::alter_table, common
+ {
+ typedef alter_table_pre base;
+
+ alter_table_pre (emitter_type& e, ostream& os, schema_format f)
+ : common (e, os), format_ (f)
+ {
+ }
+
+ virtual void
+ traverse (sema_rel::alter_table& at)
+ {
+ if (pass_ == 1)
+ {
+ // Drop unique indexes.
+ //
+ {
+ drop_index::index_type it (drop_index::unique);
+ instance<drop_index> in (emitter (), stream (), format_, it);
+ trav_rel::unames n (*in);
+ names (at, n);
+ }
+ }
+ else
+ {
+ // Add non-unique indexes.
+ //
+ {
+ create_index::index_type it (create_index::non_unique);
+ instance<create_index> in (emitter (), stream (), format_, it);
+ trav_rel::unames n (*in);
+ names (at, n);
+ }
+ }
+ }
+
+ void
+ pass (unsigned short p)
+ {
+ pass_ = p;
+ }
+
+ protected:
+ schema_format format_;
+ unsigned short pass_;
+ };
+
+ struct changeset_pre: trav_rel::changeset, common
{
- typedef migrate_pre_changeset base;
+ typedef changeset_pre base;
- migrate_pre_changeset (emitter_type& e, ostream& os, schema_format f)
+ changeset_pre (emitter_type& e, ostream& os, schema_format f)
: common (e, os), format_ (f)
{
}
@@ -667,11 +796,58 @@ namespace relational
unsigned short pass_;
};
- struct migrate_post_changeset: trav_rel::changeset, common
+ struct alter_table_post: trav_rel::alter_table, common
+ {
+ typedef alter_table_post base;
+
+ alter_table_post (emitter_type& e, ostream& os, schema_format f)
+ : common (e, os), format_ (f)
+ {
+ }
+
+ virtual void
+ traverse (sema_rel::alter_table& at)
+ {
+ if (pass_ == 1)
+ {
+ // Drop non-unique indexes.
+ //
+ {
+ drop_index::index_type it (drop_index::non_unique);
+ instance<drop_index> in (emitter (), stream (), format_, it);
+ trav_rel::unames n (*in);
+ names (at, n);
+ }
+ }
+ else
+ {
+ // Add unique indexes.
+ //
+ {
+ create_index::index_type it (create_index::unique);
+ instance<create_index> in (emitter (), stream (), format_, it);
+ trav_rel::unames n (*in);
+ names (at, n);
+ }
+ }
+ }
+
+ void
+ pass (unsigned short p)
+ {
+ pass_ = p;
+ }
+
+ protected:
+ schema_format format_;
+ unsigned short pass_;
+ };
+
+ struct changeset_post: trav_rel::changeset, common
{
- typedef migrate_post_changeset base;
+ typedef changeset_post base;
- migrate_post_changeset (emitter_type& e, ostream& os, schema_format f)
+ changeset_post (emitter_type& e, ostream& os, schema_format f)
: common (e, os), format_ (f)
{
}
diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx
index 11587ab..bd694e7 100644
--- a/odb/relational/sqlite/schema.cxx
+++ b/odb/relational/sqlite/schema.cxx
@@ -73,9 +73,25 @@ namespace relational
return quote_id (
static_cast<sema_rel::table&> (in.scope ()).name ().uname ());
}
-
};
entry<create_index> create_index_;
+
+ struct drop_index: relational::drop_index, context
+ {
+ drop_index (base const& x): base (x) {}
+
+ virtual string
+ name (sema_rel::index& in)
+ {
+ // In SQLite, index names can be qualified with the database.
+ //
+ sema_rel::table& t (static_cast<sema_rel::table&> (in.scope ()));
+ sema_rel::qname n (t.name ().qualifier ());
+ n.append (in.name ());
+ return quote_id (n);
+ }
+ };
+ entry<drop_index> drop_index_;
}
}
}