diff --git a/ChangeLog b/ChangeLog index f0230a64f3c021aeff6fc126aa9a1d8342ae4972..324d0704a30225f3594cebde9b7d22e853e85496 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2010-03-10 The InnoDB Team + + * trx/trx0sys.c: + Fix Bug #51653 outdated reference to set-variable + +2010-03-10 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb_bug21704.result, + mysql-test/innodb_bug47621.result, mysql-test/innodb_bug47621.test: + Fix Bug #47621 MySQL and InnoDB data dictionaries will become + out of sync when renaming columns + 2010-03-10 The InnoDB Team * handler/ha_innodb.cc: diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index e40b1e17bfbf71bea2f1bbfabc6c18dd7d9d2607..b95eb7d6f3f5fc2a41e463578468c684a1a365bc 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -9833,33 +9833,60 @@ innobase_set_cursor_view( (cursor_view_t*) curview); } +/*******************************************************************//** +If col_name is not NULL, check whether the named column is being +renamed in the table. If col_name is not provided, check +whether any one of columns in the table is being renamed. +@return true if the column is being renamed */ +static +bool +check_column_being_renamed( +/*=======================*/ + const TABLE* table, /*!< in: MySQL table */ + const char* col_name) /*!< in: name of the column */ +{ + uint k; + Field* field; -/*********************************************************************** -Check whether any of the given columns is being renamed in the table. */ + for (k = 0; k < table->s->fields; k++) { + field = table->field[k]; + + if (field->flags & FIELD_IS_RENAMED) { + + /* If col_name is not provided, return + if the field is marked as being renamed. */ + if (!col_name) { + return(true); + } + + /* If col_name is provided, return only + if names match */ + if (innobase_strcasecmp(field->field_name, + col_name) == 0) { + return(true); + } + } + } + + return(false); +} + +/*******************************************************************//** +Check whether any of the given columns is being renamed in the table. +@return true if any of col_names is being renamed in table */ static bool column_is_being_renamed( /*====================*/ - /* out: true if any of col_names is - being renamed in table */ - TABLE* table, /* in: MySQL table */ - uint n_cols, /* in: number of columns */ - const char** col_names) /* in: names of the columns */ + TABLE* table, /*!< in: MySQL table */ + uint n_cols, /*!< in: number of columns */ + const char** col_names) /*!< in: names of the columns */ { uint j; - uint k; - Field* field; - const char* col_name; for (j = 0; j < n_cols; j++) { - col_name = col_names[j]; - for (k = 0; k < table->s->fields; k++) { - field = table->field[k]; - if ((field->flags & FIELD_IS_RENAMED) - && innobase_strcasecmp(field->field_name, - col_name) == 0) { - return(true); - } + if (check_column_being_renamed(table, col_names[j])) { + return(true); } } @@ -9943,6 +9970,15 @@ ha_innobase::check_if_incompatible_data( return(COMPATIBLE_DATA_NO); } + /* For column rename operation, MySQL does not supply enough + information (new column name etc.) for InnoDB to make appropriate + system metadata change. To avoid system metadata inconsistency, + currently we can just request a table rebuild/copy by returning + COMPATIBLE_DATA_NO */ + if (check_column_being_renamed(table, NULL)) { + return COMPATIBLE_DATA_NO; + } + /* Check if a column participating in a foreign key is being renamed. There is no mechanism for updating InnoDB foreign key definitions. */ if (foreign_key_column_is_being_renamed(prebuilt, table)) { diff --git a/mysql-test/innodb_bug21704.result b/mysql-test/innodb_bug21704.result index b8e0b15d50db2a5bf68713041444ceab5036f3d1..ffbfa8a337e0e9226fc8ba8102d382d3e74b533c 100644 --- a/mysql-test/innodb_bug21704.result +++ b/mysql-test/innodb_bug21704.result @@ -25,8 +25,8 @@ ALTER TABLE t1 CHANGE a c INT; ERROR HY000: Error on rename of '#sql-temporary' to './test/t1' (errno: 150) # Ensure that online column rename works. ALTER TABLE t1 CHANGE b c INT; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 # Test renaming the column in the referencing table @@ -34,8 +34,8 @@ ALTER TABLE t2 CHANGE a c INT; ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150) # Ensure that online column rename works. ALTER TABLE t2 CHANGE b c INT; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 # Test with self-referential constraints @@ -45,8 +45,8 @@ ALTER TABLE t3 CHANGE b d INT; ERROR HY000: Error on rename of '#sql-temporary' to './test/t3' (errno: 150) # Ensure that online column rename works. ALTER TABLE t3 CHANGE c d INT; -affected rows: 0 -info: Records: 0 Duplicates: 0 Warnings: 0 +affected rows: 3 +info: Records: 3 Duplicates: 0 Warnings: 0 # Cleanup. diff --git a/mysql-test/innodb_bug47621.result b/mysql-test/innodb_bug47621.result new file mode 100644 index 0000000000000000000000000000000000000000..c5f56c09788653f755447ec47557d17ff5f37ab7 --- /dev/null +++ b/mysql-test/innodb_bug47621.result @@ -0,0 +1,21 @@ +CREATE TABLE bug47621 (salesperson INT) ENGINE=InnoDB; +ALTER TABLE bug47621 CHANGE salesperson sales_acct_id INT; +create index orgs on bug47621(sales_acct_id); +ALTER TABLE bug47621 CHANGE sales_acct_id salesperson INT; +drop table bug47621; +CREATE TABLE bug47621_sale ( +salesperson INT, +PRIMARY KEY(salesperson)) engine = innodb; +CREATE TABLE bug47621_shirt( +id SMALLINT, +owner INT, +FOREIGN KEY(owner) +references bug47621_sale(salesperson) ON DELETE RESTRICT) +engine = innodb; +insert into bug47621_sale values(9); +insert into bug47621_shirt values(1, 9); +ALTER TABLE bug47621_shirt CHANGE id new_id INT; +drop table bug47621_shirt; +ALTER TABLE bug47621_sale CHANGE salesperson sales_acct_id INT; +ALTER TABLE bug47621_sale ADD INDEX idx (sales_acct_id); +drop table bug47621_sale; diff --git a/mysql-test/innodb_bug47621.test b/mysql-test/innodb_bug47621.test new file mode 100644 index 0000000000000000000000000000000000000000..4863cc6bba11830238e0c63d488c1a121b09ba83 --- /dev/null +++ b/mysql-test/innodb_bug47621.test @@ -0,0 +1,57 @@ +# This is the test for bug #47621, column rename operation should +# not result in column definition inconsistency between MySQL and +# InnoDB + +--source include/have_innodb.inc + +CREATE TABLE bug47621 (salesperson INT) ENGINE=InnoDB; + +# Change the column name +ALTER TABLE bug47621 CHANGE salesperson sales_acct_id INT; + +# If there is inconsistency of column name definition +# in MySQL or InnoDB, following create index would fail +create index orgs on bug47621(sales_acct_id); + +# Change the column name back with the index defined on it. +ALTER TABLE bug47621 CHANGE sales_acct_id salesperson INT; + +drop table bug47621; + +CREATE TABLE bug47621_sale ( + salesperson INT, + PRIMARY KEY(salesperson)) engine = innodb; + +CREATE TABLE bug47621_shirt( + id SMALLINT, + owner INT, + FOREIGN KEY(owner) + references bug47621_sale(salesperson) ON DELETE RESTRICT) + engine = innodb; + +insert into bug47621_sale values(9); + +insert into bug47621_shirt values(1, 9); + +# Any rename operation on columns involved in a reference constraint will +# fail, as it will be rejected by InnoDB row_rename_table_for_mysql(). +# In above example, any rename on column "salesperson" for table +# "bug47621_sale", or on column "owner" for table "bug47621_shirt will +# be blocked. We do not put such rename in the test since InnoDB error +# message will be printed in the error log, and result in test failure. +# +# ALTER TABLE bug47621_sale CHANGE salesperson sales_acct_id INT; + +# Any rename on columns not involved in the foreign key constraint +# could still proceed +ALTER TABLE bug47621_shirt CHANGE id new_id INT; + +# Referencing table dropped, the rename operation on related columns +# could proceed +drop table bug47621_shirt; + +ALTER TABLE bug47621_sale CHANGE salesperson sales_acct_id INT; + +ALTER TABLE bug47621_sale ADD INDEX idx (sales_acct_id); + +drop table bug47621_sale; diff --git a/plug.in b/plug.in index 09a95ecc157a84eb9f5b82da99cf5603b37b468e..471ef6c69d98a3687cdcb833c70ee3d9156b2b2a 100644 --- a/plug.in +++ b/plug.in @@ -14,7 +14,7 @@ # Place, Suite 330, Boston, MA 02111-1307 USA # -MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], +MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], [Transactional Tables using InnoDB], [max,max-no-ndb]) MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase]) MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a]) diff --git a/trx/trx0sys.c b/trx/trx0sys.c index 253619545afb7d95ca84ae062a2e3b26c327d17c..ba25662c8fb16a409157cb1ac67097222bd63f4b 100644 --- a/trx/trx0sys.c +++ b/trx/trx0sys.c @@ -584,8 +584,8 @@ trx_sys_doublewrite_init_or_restore_pages( " recover the database" " with the my.cnf\n" "InnoDB: option:\n" - "InnoDB: set-variable=" - "innodb_force_recovery=6\n"); + "InnoDB:" + " innodb_force_recovery=6\n"); exit(1); }