From c19972fc8708778bd6070715b449351a39edb0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 11 Dec 2015 14:33:41 +0200 Subject: [PATCH] MDEV-9251: Fix MySQL Bug#20755615: InnoDB compares column names case sensitively, while according to Storage Engine API column names should be compared case insensitively. This can cause FRM and InnoDB data dictionary to go out of sync. --- mysql-test/suite/innodb/r/innodb-dict.result | 40 ++++++++++++++++++++ mysql-test/suite/innodb/t/innodb-dict.test | 31 +++++++++++++++ storage/innobase/dict/dict0dict.c | 2 +- storage/xtradb/dict/dict0dict.c | 2 +- 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-dict.result create mode 100644 mysql-test/suite/innodb/t/innodb-dict.test diff --git a/mysql-test/suite/innodb/r/innodb-dict.result b/mysql-test/suite/innodb/r/innodb-dict.result new file mode 100644 index 00000000000..e3b2f0d5288 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-dict.result @@ -0,0 +1,40 @@ +CREATE TABLE t1 (D INT) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN d INT; +ALTER TABLE t1 ADD INDEX my_d (d); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d` int(11) DEFAULT NULL, + KEY `my_d` (`d`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +EXPLAIN SELECT d FROM t1 WHERE d = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref my_d my_d 5 const 128 Using index +EXPLAIN SELECT D FROM t1 WHERE D = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref my_d my_d 5 const 128 Using index +ALTER TABLE t1 DROP INDEX my_d; +ALTER TABLE t1 MODIFY COLUMN D INT; +ALTER TABLE t1 ADD INDEX my_d (D); +EXPLAIN SELECT d FROM t1 WHERE d = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref my_d my_d 5 const 128 Using index +EXPLAIN SELECT D FROM t1 WHERE D = 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref my_d my_d 5 const 128 Using index +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `D` int(11) DEFAULT NULL, + KEY `my_d` (`D`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-dict.test b/mysql-test/suite/innodb/t/innodb-dict.test new file mode 100644 index 00000000000..25a284569db --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-dict.test @@ -0,0 +1,31 @@ +--source include/have_innodb.inc + +# +# Fix MySQL Bug#20755615: InnoDB compares column names case sensitively, +# while according to Storage Engine API column names should be compared +# case insensitively. This can cause FRM and InnoDB data dictionary to +# go out of sync: +# + +CREATE TABLE t1 (D INT) ENGINE=innodb; +INSERT INTO t1 VALUES (10); +ALTER TABLE t1 MODIFY COLUMN d INT; +ALTER TABLE t1 ADD INDEX my_d (d); +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +EXPLAIN SELECT d FROM t1 WHERE d = 5; +EXPLAIN SELECT D FROM t1 WHERE D = 5; +ALTER TABLE t1 DROP INDEX my_d; +ALTER TABLE t1 MODIFY COLUMN D INT; +ALTER TABLE t1 ADD INDEX my_d (D); +EXPLAIN SELECT d FROM t1 WHERE d = 5; +EXPLAIN SELECT D FROM t1 WHERE D = 5; +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 17e9eb122df..33b110ce97a 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -2010,7 +2010,7 @@ dict_index_find_cols( dict_field_t* field = dict_index_get_nth_field(index, i); for (j = 0; j < table->n_cols; j++) { - if (!strcmp(dict_table_get_col_name(table, j), + if (!innobase_strcasecmp(dict_table_get_col_name(table, j), field->name)) { field->col = dict_table_get_nth_col(table, j); diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 7351de5de2b..87d7a3b2403 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -2142,7 +2142,7 @@ dict_index_find_cols( dict_field_t* field = dict_index_get_nth_field(index, i); for (j = 0; j < table->n_cols; j++) { - if (!strcmp(dict_table_get_col_name(table, j), + if (!innobase_strcasecmp(dict_table_get_col_name(table, j), field->name)) { field->col = dict_table_get_nth_col(table, j);