diff --git a/mysql-test/r/lowercase_table4.result b/mysql-test/r/lowercase_table4.result new file mode 100755 index 00000000000..e3f861f8884 --- /dev/null +++ b/mysql-test/r/lowercase_table4.result @@ -0,0 +1,7 @@ +# +# Bug#46941 crash with lower_case_table_names=2 and +# foreign data dictionary confusion +# +CREATE DATABASE XY; +USE XY; +DROP DATABASE XY; diff --git a/mysql-test/t/lowercase_table4-master.opt b/mysql-test/t/lowercase_table4-master.opt new file mode 100755 index 00000000000..c0a1981fa7c --- /dev/null +++ b/mysql-test/t/lowercase_table4-master.opt @@ -0,0 +1 @@ +--lower-case-table-names=2 diff --git a/mysql-test/t/lowercase_table4.test b/mysql-test/t/lowercase_table4.test new file mode 100755 index 00000000000..93956047145 --- /dev/null +++ b/mysql-test/t/lowercase_table4.test @@ -0,0 +1,56 @@ +--source include/have_case_insensitive_file_system.inc +--source include/have_innodb.inc + +--echo # +--echo # Bug#46941 crash with lower_case_table_names=2 and +--echo # foreign data dictionary confusion +--echo # + +CREATE DATABASE XY; +USE XY; + +# +# Logs are disabled, since the number of creates tables +# and subsequent select statements may vary between +# versions +# +--disable_query_log +--disable_result_log + +let $tcs = `SELECT @@table_open_cache + 1`; + +let $i = $tcs; + +while ($i) +{ + eval CREATE TABLE XY.T_$i (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, + primary key(a, b), unique(b)) ENGINE=InnoDB; + dec $i; +} + +eval ALTER TABLE XY.T_$tcs ADD INDEX I1 (c, b), + ADD CONSTRAINT C1 FOREIGN KEY (c, b) REFERENCES XY.T_1 (a, b); + +eval ALTER TABLE XY.T_$tcs ADD INDEX I2 (b), + ADD CONSTRAINT C2 FOREIGN KEY (b) REFERENCES XY.T_1(a); + +let $i = $tcs; +while ($i) +{ + eval SELECT * FROM XY.T_$i LIMIT 1; + dec $i; +} + +DROP DATABASE XY; +CREATE DATABASE XY; +USE XY; +eval CREATE TABLE XY.T_$tcs (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, + PRIMARY KEY(a, b), UNIQUE(b)) ENGINE=InnoDB; +# +# The bug causes this SELECT to err +eval SELECT * FROM XY.T_$tcs LIMIT 1; + +--enable_query_log +--enable_result_log +DROP DATABASE XY; + diff --git a/sql/sql_db.cc b/sql/sql_db.cc index d3435b891b1..2c44c1a8449 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1197,6 +1197,12 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, VOID(filename_to_tablename(file->name, table_list->table_name, MYSQL50_TABLE_NAME_PREFIX_LENGTH + strlen(file->name) + 1)); + + /* To be able to correctly look up the table in the table cache. */ + if (lower_case_table_names) + table_list->table_name_length= my_casedn_str(files_charset_info, + table_list->table_name); + table_list->alias= table_list->table_name; // If lower_case_table_names=2 table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix); /* Link into list */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 04cc9e42413..971e1022d63 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3896,7 +3896,7 @@ bool mysql_create_table_no_lock(THD *thd, Then she could create the table. This case is pretty obscure and therefore we don't introduce a new error message only for it. */ - if (get_cached_table_share(db, alias)) + if (get_cached_table_share(db, table_name)) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); goto unlock_and_end;