From ea9dbef661efdf5079b1b0e33679a863408e3166 Mon Sep 17 00:00:00 2001 From: Aditya A Date: Tue, 22 Sep 2015 16:52:18 +0530 Subject: [PATCH] Bug#20755615 CREATING INDEX ON A RENAMED COLUMN WITH CASE CRASH .FRM FILE PROBLEM In 5.5 when doing doing a rename of a column ,we ignore the case between old and new column names while comparing them,so if the change is just the case then we don't even mark the field FIELD_IS_RENAMED ,we just update the frm file ,but don't recreate the table as is the norm when alter is used.This leads to inconsistency in the innodb data dictionary which causes index creation to fail. FIX According to the documentation any innodb column rename should trigger rebuild of the table. Therefore for innodb tables we will do a strcmp() between the column names and if there is case change in column name we will trigger a rebuild. --- mysql-test/r/alter_table.result | 17 +++++++++++++++++ mysql-test/t/alter_table.test | 19 +++++++++++++++++++ sql/sql_table.cc | 20 ++++++++++++++++---- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 236d07bccbc..725f2528c29 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -1488,3 +1488,20 @@ CREATE TABLE help_topic (dummy int) ENGINE=innodb; ERROR HY000: Storage engine 'InnoDB' does not support system tables. [mysql.help_topic] use test; # End of Bug#11815557 +# +# Bug#20755615 CREATING INDEX ON A RENAMED +# COLUMN WITH CASE CRASH .FRM FILE +# +CREATE TABLE t1 (D INT) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN d INT; +ALTER TABLE t1 ADD INDEX (d); +DROP TABLE t1; +CREATE TABLE t1 (`é` int) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 CHANGE `é` `É` INT; +ALTER TABLE t1 ADD INDEX (`É`); +SELECT * FROM t1; +É +10 +DROP TABLE t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index f5d5538c217..8768cd4975c 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1261,3 +1261,22 @@ CREATE TABLE time_zone (dummy int) ENGINE=merge; CREATE TABLE help_topic (dummy int) ENGINE=innodb; use test; --echo # End of Bug#11815557 + +--echo # +--echo # Bug#20755615 CREATING INDEX ON A RENAMED +--echo # COLUMN WITH CASE CRASH .FRM FILE +--echo # + +CREATE TABLE t1 (D INT) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN d INT; +ALTER TABLE t1 ADD INDEX (d); +DROP TABLE t1; + +CREATE TABLE t1 (`é` int) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 CHANGE `é` `É` INT; +ALTER TABLE t1 ADD INDEX (`É`); +SELECT * FROM t1; +DROP TABLE t1; + diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2951d921e15..0a58d9ade5b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5048,10 +5048,22 @@ mysql_compare_tables(TABLE *table, /* Check if field was renamed */ field->flags&= ~FIELD_IS_RENAMED; - if (my_strcasecmp(system_charset_info, - field->field_name, - tmp_new_field->field_name)) - field->flags|= FIELD_IS_RENAMED; + + /* + InnoDB data dictionary is case sensitive so we should use string case + sensitive comparison between fields. Note: strcmp branch is to be + removed in future when we fix it in InnoDB. + */ + if ((table->s->db_type())->db_type == DB_TYPE_INNODB && + strcmp(field->field_name,tmp_new_field->field_name)) + field->flags|= FIELD_IS_RENAMED; + else + { + if (my_strcasecmp(system_charset_info, + field->field_name, + tmp_new_field->field_name)) + field->flags|= FIELD_IS_RENAMED; + } /* Evaluate changes bitmap and send to check_if_incompatible_data() */ if (!(tmp= field->is_equal(tmp_new_field)))