From 6d4b471afd63780b8a8a6c2d3fb8cc529ab5b15d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 4 Apr 2013 09:47:32 +0200 Subject: Generate add/drop index migration statements --- odb/relational/mssql/schema.cxx | 15 +++ odb/relational/mysql/schema.cxx | 15 +++ odb/relational/oracle/schema.cxx | 19 +++- odb/relational/schema.cxx | 18 +++- odb/relational/schema.hxx | 216 +++++++++++++++++++++++++++++++++++---- odb/relational/sqlite/schema.cxx | 18 +++- 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 (in.scope ())); + + os << "DROP INDEX " << name (in) << " ON " << + quote_id (t.name ()) << endl; + } + }; + entry 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_; + + 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 (in.scope ())); + + os << "DROP INDEX " << name (in) << " ON " << + quote_id (t.name ()) << endl; + } + }; + entry 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_; + + 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 (in.scope ())); + sema_rel::qname n (t.name ().qualifier ()); + n.append (in.name ()); + return quote_id (n); + } + }; + entry 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 changeset (*em, emos, f); + instance changeset (*em, emos, f); instance ctable (*em, emos, f); + instance 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 changeset (*em, emos, f); + instance changeset (*em, emos, f); instance dtable (*em, emos, f); + instance 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 (di.scope ())); + changeset& cs (dynamic_cast (at.scope ())); + model& bm (cs.base_model ()); + table* bt (bm.find (at.name ())); + assert (bt != 0); + index* bi (bt->find (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 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 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 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 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 (in.scope ()).name ().uname ()); } - }; entry 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 (in.scope ())); + sema_rel::qname n (t.name ().qualifier ()); + n.append (in.name ()); + return quote_id (n); + } + }; + entry drop_index_; } } } -- cgit v1.1