From adfa9bbd04cd3571932ee7675344ca723bfa1eab Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 20 Jul 2012 14:26:23 +0200 Subject: Move indexes from model scope to table scope Conceptually, indexes belong to tables and some databases (MySQL, MSSQL) indeed treat them as such (i.e., you can have indexes with the same name in different tables). --- odb/relational/model.hxx | 7 +- odb/relational/mssql/schema.cxx | 14 --- odb/relational/mysql/schema.cxx | 14 --- odb/relational/oracle/schema.cxx | 20 +++ odb/relational/pgsql/schema.cxx | 8 +- odb/relational/schema.cxx | 17 +-- odb/relational/schema.hxx | 205 +++++++++++++++---------------- odb/relational/sqlite/schema.cxx | 20 ++- odb/semantics/relational/elements.hxx | 8 +- odb/semantics/relational/foreign-key.hxx | 4 +- odb/semantics/relational/index.hxx | 19 +-- odb/semantics/relational/key.hxx | 4 +- odb/semantics/relational/primary-key.hxx | 7 +- 13 files changed, 164 insertions(+), 183 deletions(-) diff --git a/odb/relational/model.hxx b/odb/relational/model.hxx index d41b701..b95425e 100644 --- a/odb/relational/model.hxx +++ b/odb/relational/model.hxx @@ -471,9 +471,7 @@ namespace relational id_name += '_'; model_.new_edge (t, fk, id_name + "fk"); - - model_.new_edge ( - model_, in, name + "_" + id_name + "i"); + model_.new_edge (t, in, id_name + "i"); } // index (simple value) @@ -492,8 +490,7 @@ namespace relational model_.new_edge ( in, dynamic_cast (t.find (col_name)->nameable ())); - model_.new_edge ( - model_, in, name + "_" + col_name + "_i"); + model_.new_edge (t, in, col_name + "_i"); } // key diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx index ebbda2c..47cb250 100644 --- a/odb/relational/mssql/schema.cxx +++ b/odb/relational/mssql/schema.cxx @@ -288,20 +288,6 @@ namespace relational trav_rel::unames n (fk); names (t, n); } - - struct create_index: relational::create_index, context - { - create_index (base const& x): base (x) {} - - virtual string - name (sema_rel::index& in) - { - // In SQL Server indexes cannot have a schema. - // - return quote_id (in.name ().uname ()); - } - }; - entry create_index_; } } } diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx index 6db30ad..4050d70 100644 --- a/odb/relational/mysql/schema.cxx +++ b/odb/relational/mysql/schema.cxx @@ -125,20 +125,6 @@ namespace relational } }; entry create_table_; - - struct create_index: relational::create_index, context - { - create_index (base const& x): base (x) {} - - virtual string - name (sema_rel::index& in) - { - // In MySQL an index cannot be qualified with the database name. - // - return quote_id (in.name ().uname ()); - } - }; - entry create_index_; } } } diff --git a/odb/relational/oracle/schema.cxx b/odb/relational/oracle/schema.cxx index ce2c470..29c1130 100644 --- a/odb/relational/oracle/schema.cxx +++ b/odb/relational/oracle/schema.cxx @@ -302,6 +302,26 @@ namespace relational trav_rel::unames n (fk); names (t, n); } + + struct create_index: relational::create_index, context + { + create_index (base const& x): base (x) {} + + virtual string + name (sema_rel::index& in) + { + // In Oracle, index names are database-global. Make them unique + // by prefixing the index name with table name (preserving the + // schema). + // + sema_rel::qname n ( + static_cast (in.scope ()).name ()); + + n.uname () += "_" + in.name (); + return quote_id (n); + } + }; + entry create_index_; } } } diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx index c774561..2113894 100644 --- a/odb/relational/pgsql/schema.cxx +++ b/odb/relational/pgsql/schema.cxx @@ -173,9 +173,13 @@ namespace relational virtual string name (sema_rel::index& in) { - // In PostgreSQL indexes cannot have a schema. + // In PostgreSQL, index names are database-global. Make them unique + // by prefixing the index name with table name. Note, however, that + // they cannot be qualified with the schema name. // - return quote_id (in.name ().uname ()); + return quote_id ( + static_cast (in.scope ()).name ().uname () + + "_" + in.name ()); } }; entry create_index_; diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx index ea9083d..3dd8507 100644 --- a/odb/relational/schema.cxx +++ b/odb/relational/schema.cxx @@ -45,15 +45,11 @@ namespace relational // Drop. // { - instance model (*em, emos, f); - trav_rel::qnames names; instance table (*em, emos, f); - instance index (*em, emos, f); + trav_rel::qnames names; - model >> names; - names >> table; - names >> index; + model >> names >> table; // Pass 1 and 2. // @@ -61,7 +57,6 @@ namespace relational { model->pass (pass); table->pass (pass); - index->pass (pass); model->traverse (*ctx.model); } @@ -73,13 +68,10 @@ namespace relational // { instance model (*em, emos, f); - trav_rel::qnames names; instance table (*em, emos, f); - instance index (*em, emos, f); + trav_rel::qnames names; - model >> names; - names >> table; - names >> index; + model >> names >> table; // Pass 1 and 2. // @@ -87,7 +79,6 @@ namespace relational { model->pass (pass); table->pass (pass); - index->pass (pass); model->traverse (*ctx.model); } diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 4f31dca..6551119 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -58,65 +58,65 @@ namespace relational // Drop. // - struct drop_table: trav_rel::table, common + struct drop_index: trav_rel::index, common { - typedef drop_table base; + typedef drop_index base; - drop_table (emitter_type& e, ostream& os, schema_format f) + drop_index (emitter_type& e, ostream& os, schema_format f) : common (e, os), format_ (f) { } - virtual void - drop (sema_rel::qname const& table) + virtual string + name (sema_rel::index& in) { - os << "DROP TABLE IF EXISTS " << quote_id (table) << endl; + return quote_id (in.name ()); + } + + virtual string + table_name (sema_rel::index& in) + { + return quote_id (static_cast (in.scope ()).name ()); } virtual void - traverse (sema_rel::table& t) + drop (string const& /*name*/, string const& /*table*/) { - // By default we do everything in a single pass. But some - // databases may require the second pass. + // Most database systems drop indexes together with the table. // - if (pass_ > 1) - return; - - pre_statement (); - drop (t.name ()); - post_statement (); + // os << "DROP INDEX IF EXISTS " << quote_id (name) << " ON " << + // table << endl; } - void - pass (unsigned short p) + virtual void + traverse (sema_rel::index& in) { - pass_ = p; + pre_statement (); + drop (name (in), table_name (in)); + post_statement (); } protected: schema_format format_; - unsigned short pass_; }; - struct drop_index: trav_rel::index, common + struct drop_table: trav_rel::table, common { - typedef drop_index base; + typedef drop_table base; - drop_index (emitter_type& e, ostream& os, schema_format f) + drop_table (emitter_type& e, ostream& os, schema_format f) : common (e, os), format_ (f) { } virtual void - drop (sema_rel::qname const& /*index*/) + drop (sema_rel::qname const& table) { - // Most database systems drop indexes together with the table. - // - //os << "DROP INDEX IF EXISTS " << quote_id (index); + os << "DROP TABLE IF EXISTS " << quote_id (table) << endl; } virtual void - traverse (sema_rel::index& in) + traverse (sema_rel::table& t) { // By default we do everything in a single pass. But some // databases may require the second pass. @@ -124,8 +124,16 @@ namespace relational if (pass_ > 1) return; + // Drop indexes. + // + { + instance in (emitter (), stream (), format_); + trav_rel::unames n (*in); + names (t, n); + } + pre_statement (); - drop (in.name ()); + drop (t.name ()); post_statement (); } @@ -456,65 +464,6 @@ namespace relational create_table& create_table_; }; - struct create_table: trav_rel::table, common - { - typedef create_table base; - - create_table (emitter_type& e, ostream& os, schema_format f) - : common (e, os), format_ (f) - { - } - - virtual void - create_pre (sema_rel::qname const& table) - { - os << "CREATE TABLE " << quote_id (table) << " (" << endl; - } - - virtual void - create_post () - { - os << ")" << endl; - } - - virtual void - traverse (sema_rel::table& t) - { - // By default we do everything in a single pass. But some - // databases may require the second pass. - // - if (pass_ > 1) - return; - - pre_statement (); - create_pre (t.name ()); - - instance c (format_, *this); - instance pk (format_, *this); - instance fk (format_, *this); - trav_rel::unames n; - - n >> c; - n >> pk; - n >> fk; - - names (t, n); - - create_post (); - post_statement (); - } - - void - pass (unsigned short p) - { - pass_ = p; - } - - protected: - schema_format format_; - unsigned short pass_; - }; - struct create_index: trav_rel::index, common { typedef create_index base; @@ -527,12 +476,6 @@ namespace relational virtual void traverse (sema_rel::index& in) { - // By default we do everything in a single pass. But some - // databases may require the second pass. - // - if (pass_ > 1) - return; - pre_statement (); create (in); post_statement (); @@ -547,7 +490,7 @@ namespace relational virtual string table_name (sema_rel::index& in) { - return quote_id (in.table ().name ()); + return quote_id (static_cast (in.scope ()).name ()); } virtual void @@ -577,6 +520,66 @@ namespace relational os << ")" << endl; } + protected: + schema_format format_; + }; + + struct create_table: trav_rel::table, common + { + typedef create_table base; + + create_table (emitter_type& e, ostream& os, schema_format f) + : common (e, os), format_ (f) + { + } + + virtual void + create_pre (sema_rel::qname const& table) + { + os << "CREATE TABLE " << quote_id (table) << " (" << endl; + } + + virtual void + create_post () + { + os << ")" << endl; + } + + virtual void + traverse (sema_rel::table& t) + { + // By default we do everything in a single pass. But some + // databases may require the second pass. + // + if (pass_ > 1) + return; + + pre_statement (); + create_pre (t.name ()); + + instance c (format_, *this); + instance pk (format_, *this); + instance fk (format_, *this); + trav_rel::unames n; + + n >> c; + n >> pk; + n >> fk; + + names (t, n); + + create_post (); + post_statement (); + + // Create indexes. + // + { + instance in (emitter (), stream (), format_); + trav_rel::unames n (*in); + names (t, n); + } + } + void pass (unsigned short p) { @@ -799,10 +802,8 @@ namespace relational : 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) + create_table_ (*emitter_, stream_, format_embedded) { init (); } @@ -813,10 +814,8 @@ namespace relational 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) + create_table_ (*emitter_, stream_, format_embedded) { init (); } @@ -826,11 +825,9 @@ namespace relational { 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 @@ -872,7 +869,6 @@ namespace relational emitter_->pass (pass); drop_model_->pass (pass); drop_table_->pass (pass); - drop_index_->pass (pass); drop_model_->traverse (begin, end); @@ -900,7 +896,6 @@ namespace relational emitter_->pass (pass); create_model_->pass (pass); create_table_->pass (pass); - create_index_->pass (pass); create_model_->traverse (begin, end); @@ -932,12 +927,10 @@ namespace relational trav_rel::qnames drop_names_; instance drop_model_; instance drop_table_; - instance drop_index_; trav_rel::qnames create_names_; instance create_model_; instance create_table_; - instance create_index_; }; } } diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx index b20c7da..8efef66 100644 --- a/odb/relational/sqlite/schema.cxx +++ b/odb/relational/sqlite/schema.cxx @@ -54,13 +54,29 @@ namespace relational create_index (base const& x): base (x) {} virtual string + name (sema_rel::index& in) + { + // In SQLite, index names are database-global. Make them unique + // by prefixing the index name with table name (preserving the + // database). + // + sema_rel::qname n ( + static_cast (in.scope ()).name ()); + + n.uname () += "_" + in.name (); + return quote_id (n); + } + + virtual string table_name (sema_rel::index& in) { // In SQLite, the index table cannot be qualified with the - // database name (it has to be in the same database anyway). + // database name (it has to be in the same database). // - return quote_id (in.table ().name ().uname ()); + return quote_id ( + static_cast (in.scope ()).name ().uname ()); } + }; entry create_index_; } diff --git a/odb/semantics/relational/elements.hxx b/odb/semantics/relational/elements.hxx index 6b4964e..8eb695a 100644 --- a/odb/semantics/relational/elements.hxx +++ b/odb/semantics/relational/elements.hxx @@ -174,10 +174,10 @@ namespace semantics public: // Id identifies the C++ node (e.g., a class or a data member) that // this model node corresponds to. The ids are not necessarily unique - // (e.g., there can be a table and an index with the same id that - // correspond to a container member). However, in any given scope, - // the {id,typeid} must be unique. This becomes important when we - // try to find correspondance between nodes during model diff'ing. + // (e.g., there can be a foreign key and an index with the same id that + // correspond to a container member). However, in any given scope, the + // {id,typeid} must be unique. This becomes important when we try to + // find correspondance between nodes during model diff'ing. // nameable (string const& id): id_ (id), named_ (0) {} diff --git a/odb/semantics/relational/foreign-key.hxx b/odb/semantics/relational/foreign-key.hxx index 83b7071..871c036 100644 --- a/odb/semantics/relational/foreign-key.hxx +++ b/odb/semantics/relational/foreign-key.hxx @@ -12,7 +12,7 @@ namespace semantics { namespace relational { - class foreign_key: public unameable, public key + class foreign_key: public key { public: enum action @@ -25,7 +25,7 @@ namespace semantics qname const& referenced_table, bool deferred, action on_delete = no_action) - : unameable (id), + : key (id), referenced_table_ (referenced_table), deferred_ (deferred), on_delete_ (on_delete) diff --git a/odb/semantics/relational/index.hxx b/odb/semantics/relational/index.hxx index dcb8e6e..af90b12 100644 --- a/odb/semantics/relational/index.hxx +++ b/odb/semantics/relational/index.hxx @@ -6,31 +6,18 @@ #define ODB_SEMANTICS_RELATIONAL_INDEX_HXX #include -#include #include -#include namespace semantics { namespace relational { - // Note that unlike other keys, indexes are defined in the model - // scope, not table scope. + // Note that in our model indexes are defined in the table scope. // - class index: public qnameable, public key + class index: public key { public: - relational::table& - table () const - { - return contains_begin ()->column ().table (); - } - - public: - index (string const& id) - : qnameable (id) - { - } + index (string const& id): key (id) {} virtual string kind () const diff --git a/odb/semantics/relational/key.hxx b/odb/semantics/relational/key.hxx index f5184be..40e7499 100644 --- a/odb/semantics/relational/key.hxx +++ b/odb/semantics/relational/key.hxx @@ -50,7 +50,7 @@ namespace semantics column_type* column_; }; - class key: public virtual node + class key: public unameable { typedef std::vector contains_list; @@ -78,6 +78,8 @@ namespace semantics } public: + key (std::string const& id): unameable (id) {} + void add_edge_left (contains& e) { diff --git a/odb/semantics/relational/primary-key.hxx b/odb/semantics/relational/primary-key.hxx index e35b00f..0aec038 100644 --- a/odb/semantics/relational/primary-key.hxx +++ b/odb/semantics/relational/primary-key.hxx @@ -12,7 +12,7 @@ namespace semantics { namespace relational { - class primary_key: public unameable, public key + class primary_key: public key { public: bool @@ -23,9 +23,8 @@ namespace semantics public: primary_key (bool auto_) - // Primary key has the implicit empty id. - // - : unameable (""), auto__ (auto_) + : key (""), // Primary key has the implicit empty id. + auto__ (auto_) { } -- cgit v1.1