From 26de9061e8c4462152b4bcff2b9cbb80cde12de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 23 Jun 2016 07:42:40 +0300 Subject: [PATCH] Merge following commit from 5.5: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ef92aaf9ece92c873ae0f3448ab2274c958ba3fe Author: Jan Lindström Date: Wed Jun 22 22:37:28 2016 +0300 MDEV-10083: Orphan ibd file when playing with foreign keys Analysis: row_drop_table_for_mysql did not allow dropping referenced table even in case when actual creating of the referenced table was not successfull if foreign_key_checks=1. Fix: Allow dropping referenced table even if foreign_key_checks=1 if actual table create returned error. --- .../suite/innodb/r/innodb-fkcheck.result | 89 ++++++++++++++ mysql-test/suite/innodb/t/innodb-fkcheck.test | 115 ++++++++++++++++++ storage/innobase/dict/dict0crea.cc | 16 +-- storage/innobase/fts/fts0fts.cc | 4 +- storage/innobase/handler/ha_innodb.cc | 6 +- storage/innobase/include/row0mysql.h | 3 + storage/innobase/row/row0merge.cc | 2 +- storage/innobase/row/row0mysql.cc | 22 ++-- storage/innobase/trx/trx0roll.cc | 2 +- storage/xtradb/dict/dict0crea.cc | 16 +-- storage/xtradb/fts/fts0fts.cc | 4 +- storage/xtradb/handler/ha_innodb.cc | 6 +- storage/xtradb/include/row0mysql.h | 3 + storage/xtradb/row/row0merge.cc | 2 +- storage/xtradb/row/row0mysql.cc | 22 ++-- storage/xtradb/trx/trx0roll.cc | 2 +- 16 files changed, 272 insertions(+), 42 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-fkcheck.result create mode 100644 mysql-test/suite/innodb/t/innodb-fkcheck.test diff --git a/mysql-test/suite/innodb/r/innodb-fkcheck.result b/mysql-test/suite/innodb/r/innodb-fkcheck.result new file mode 100644 index 00000000000..c6beabb0f50 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-fkcheck.result @@ -0,0 +1,89 @@ +set global innodb_file_per_table = 1; +drop table if exists b; +drop database if exists bug_fk; +create database bug_fk; +use bug_fk; +CREATE TABLE b ( +b int unsigned NOT NULL, +d1 datetime NOT NULL, +PRIMARY KEY (b,d1) +) ENGINE=InnoDB; +CREATE TABLE c ( +b int unsigned NOT NULL, +d1 datetime NOT NULL, +d2 datetime NOT NULL, +PRIMARY KEY (b,d1), +CONSTRAINT b_fk FOREIGN KEY (b) REFERENCES b (b) +) ENGINE=InnoDB; +show warnings; +Level Code Message +set foreign_key_checks = 0; +DROP TABLE IF EXISTS b; +show create table c; +Table Create Table +c CREATE TABLE `c` ( + `b` int(10) unsigned NOT NULL, + `d1` datetime NOT NULL, + `d2` datetime NOT NULL, + PRIMARY KEY (`b`,`d1`), + CONSTRAINT `b_fk` FOREIGN KEY (`b`) REFERENCES `b` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +CREATE TABLE b ( +b bigint unsigned NOT NULL, +d1 date NOT NULL, +PRIMARY KEY (b,d1) +) ENGINE=InnoDB; +ERROR HY000: Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") +show warnings; +Level Code Message +Error 1005 Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") +Warning 1215 Cannot add foreign key constraint +DROP TABLE IF EXISTS d; +Warnings: +Note 1051 Unknown table 'bug_fk.d' +CREATE TABLE d ( +b bigint unsigned NOT NULL, +d1 date NOT NULL, +PRIMARY KEY (b,d1), +CONSTRAINT bd_fk FOREIGN KEY (b) REFERENCES b (b) +) ENGINE=InnoDB; +show warnings; +Level Code Message +set foreign_key_checks = 1; +show create table c; +Table Create Table +c CREATE TABLE `c` ( + `b` int(10) unsigned NOT NULL, + `d1` datetime NOT NULL, + `d2` datetime NOT NULL, + PRIMARY KEY (`b`,`d1`), + CONSTRAINT `b_fk` FOREIGN KEY (`b`) REFERENCES `b` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table d; +Table Create Table +d CREATE TABLE `d` ( + `b` bigint(20) unsigned NOT NULL, + `d1` date NOT NULL, + PRIMARY KEY (`b`,`d1`), + CONSTRAINT `bd_fk` FOREIGN KEY (`b`) REFERENCES `b` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +CREATE TABLE b ( +b bigint unsigned NOT NULL, +d1 date NOT NULL, +PRIMARY KEY (b,d1) +) ENGINE=InnoDB; +ERROR HY000: Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") +show warnings; +Level Code Message +Error 1005 Can't create table `bug_fk`.`b` (errno: 150 "Foreign key constraint is incorrectly formed") +Warning 1215 Cannot add foreign key constraint +set foreign_key_checks=0; +drop table c; +drop table d; +create table b(id int) engine=innodb; +show warnings; +Level Code Message +b.frm +b.ibd +drop table if exists b; +drop database if exists bug_fk; diff --git a/mysql-test/suite/innodb/t/innodb-fkcheck.test b/mysql-test/suite/innodb/t/innodb-fkcheck.test new file mode 100644 index 00000000000..51e36ae6984 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-fkcheck.test @@ -0,0 +1,115 @@ +--source include/have_innodb.inc + +# +# MDEV-10083: Orphan ibd file when playing with foreign keys +# +--disable_query_log +SET @start_global_fpt = @@global.innodb_file_per_table; +SET @start_global_fkc = @@global.foreign_key_checks; +--enable_query_log + +set global innodb_file_per_table = 1; + +--disable_warnings +drop table if exists b; +drop database if exists bug_fk; +--enable_warnings + +let $MYSQLD_DATADIR = `select @@datadir`; + +create database bug_fk; +use bug_fk; + +CREATE TABLE b ( + b int unsigned NOT NULL, + d1 datetime NOT NULL, + PRIMARY KEY (b,d1) +) ENGINE=InnoDB; + +CREATE TABLE c ( + b int unsigned NOT NULL, + d1 datetime NOT NULL, + d2 datetime NOT NULL, + PRIMARY KEY (b,d1), + CONSTRAINT b_fk FOREIGN KEY (b) REFERENCES b (b) +) ENGINE=InnoDB; + +show warnings; + +set foreign_key_checks = 0; + +DROP TABLE IF EXISTS b; + +show create table c; + +# +# Note that column b has different type in parent table +# +--error 1005 +CREATE TABLE b ( + b bigint unsigned NOT NULL, + d1 date NOT NULL, + PRIMARY KEY (b,d1) +) ENGINE=InnoDB; + +show warnings; + +DROP TABLE IF EXISTS d; + +CREATE TABLE d ( + b bigint unsigned NOT NULL, + d1 date NOT NULL, + PRIMARY KEY (b,d1), + CONSTRAINT bd_fk FOREIGN KEY (b) REFERENCES b (b) +) ENGINE=InnoDB; + +show warnings; + +set foreign_key_checks = 1; + +show create table c; +show create table d; + +# +# Table c column b used on foreign key has different type +# compared referenced column b in table b, but this +# create still produced b.ibd file. This is because +# we row_drop_table_for_mysql was called and referenced +# table is not allowed to be dropped even in case +# when actual create is not successfull. +# +--error 1005 +CREATE TABLE b ( + b bigint unsigned NOT NULL, + d1 date NOT NULL, + PRIMARY KEY (b,d1) +) ENGINE=InnoDB; + +show warnings; + +--list_files $MYSQLD_DATADIR/bug_fk b* + +set foreign_key_checks=0; + +drop table c; +drop table d; + +--list_files $MYSQLD_DATADIR/bug_fk b* + +create table b(id int) engine=innodb; +show warnings; + +--list_files $MYSQLD_DATADIR/bug_fk b* + +# +# Cleanup +# +--disable_query_log +SET @@global.innodb_file_per_table = @start_global_fpt; +SET @@global.foreign_key_checks = @start_global_fkc; +--enable_query_log + +--disable_warnings +drop table if exists b; +drop database if exists bug_fk; +--enable_warnings diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 2706ed9be4d..3c140dbb07e 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1365,7 +1365,7 @@ dict_create_or_check_foreign_constraint_tables(void) ib_logf(IB_LOG_LEVEL_WARN, "Dropping incompletely created " "SYS_FOREIGN table."); - row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE); } if (sys_foreign_cols_err == DB_CORRUPTION) { @@ -1373,7 +1373,7 @@ dict_create_or_check_foreign_constraint_tables(void) "Dropping incompletely created " "SYS_FOREIGN_COLS table."); - row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE); } ib_logf(IB_LOG_LEVEL_WARN, @@ -1427,8 +1427,8 @@ dict_create_or_check_foreign_constraint_tables(void) ut_ad(err == DB_OUT_OF_FILE_SPACE || err == DB_TOO_MANY_CONCURRENT_TRXS); - row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); - row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE); if (err == DB_OUT_OF_FILE_SPACE) { err = DB_MUST_GET_MORE_FILE_SPACE; @@ -1853,7 +1853,7 @@ dict_create_or_check_sys_tablespace(void) ib_logf(IB_LOG_LEVEL_WARN, "Dropping incompletely created " "SYS_TABLESPACES table."); - row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE); + row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE, TRUE); } if (sys_datafiles_err == DB_CORRUPTION) { @@ -1861,7 +1861,7 @@ dict_create_or_check_sys_tablespace(void) "Dropping incompletely created " "SYS_DATAFILES table."); - row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE); + row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE, TRUE); } ib_logf(IB_LOG_LEVEL_INFO, @@ -1897,8 +1897,8 @@ dict_create_or_check_sys_tablespace(void) ut_a(err == DB_OUT_OF_FILE_SPACE || err == DB_TOO_MANY_CONCURRENT_TRXS); - row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE); - row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE); + row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE, TRUE); + row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE, TRUE); if (err == DB_OUT_OF_FILE_SPACE) { err = DB_MUST_GET_MORE_FILE_SPACE; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 2eac5dcac86..99865f20f68 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1918,7 +1918,7 @@ func_exit: trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(table->name, trx, FALSE); + row_drop_table_for_mysql(table->name, trx, FALSE, TRUE); trx->error_state = DB_SUCCESS; } @@ -2070,7 +2070,7 @@ fts_create_index_tables_low( trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, TRUE); trx->error_state = DB_SUCCESS; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 06fd6591d89..9d976d685ed 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -10686,7 +10686,8 @@ ha_innobase::delete_table( /* Drop the table in InnoDB */ err = row_drop_table_for_mysql( - norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB); + norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB, + FALSE); if (err == DB_TABLE_NOT_FOUND @@ -10717,7 +10718,8 @@ ha_innobase::delete_table( #endif err = row_drop_table_for_mysql( par_case_name, trx, - thd_sql_command(thd) == SQLCOM_DROP_DB); + thd_sql_command(thd) == SQLCOM_DROP_DB, + FALSE); } } diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index fc1846b76f3..f5f159fc414 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -488,6 +488,9 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: dictionary transaction handle */ bool drop_db,/*!< in: true=dropping whole database */ + ibool create_failed,/*!n_ref_count == 0); - return(row_drop_table_for_mysql(table->name, trx, false, false)); + return(row_drop_table_for_mysql(table->name, trx, false, false, false)); } /*********************************************************************//** diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 4c3fa5364b7..122c03b7cc9 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2391,7 +2391,7 @@ err_exit: dict_table_close(table, TRUE, FALSE); - row_drop_table_for_mysql(table->name, trx, FALSE); + row_drop_table_for_mysql(table->name, trx, FALSE, TRUE); if (commit) { trx_commit_for_mysql(trx); @@ -2551,7 +2551,7 @@ error_handling: trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); @@ -2628,7 +2628,7 @@ row_table_add_foreign_constraints( trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(name, trx, FALSE); + row_drop_table_for_mysql(name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); @@ -2669,7 +2669,7 @@ row_drop_table_for_mysql_in_background( /* Try to drop the table in InnoDB */ - error = row_drop_table_for_mysql(name, trx, FALSE); + error = row_drop_table_for_mysql(name, trx, FALSE, FALSE); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -3767,6 +3767,9 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: transaction handle */ bool drop_db,/*!< in: true=dropping whole database */ + ibool create_failed,/*!foreign_table_name_lookup); - if (foreign->foreign_table != table && !ref_ok) { + /* We should allow dropping a referenced table if creating + that referenced table has failed for some reason. For example + if referenced table is created but it column types that are + referenced do not match. */ + if (foreign->foreign_table != table && + !create_failed && !ref_ok) { FILE* ef = dict_foreign_err_file; @@ -4497,7 +4505,7 @@ row_mysql_drop_temp_tables(void) table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE); if (table) { - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, FALSE); trx_commit_for_mysql(trx); } @@ -4666,7 +4674,7 @@ loop: goto loop; } - err = row_drop_table_for_mysql(table_name, trx, TRUE); + err = row_drop_table_for_mysql(table_name, trx, TRUE, FALSE); trx_commit_for_mysql(trx); if (err != DB_SUCCESS) { diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 95cab752c32..c65d95a9817 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -641,7 +641,7 @@ trx_rollback_active( "in recovery", table->name, trx->table_id); - err = row_drop_table_for_mysql(table->name, trx, TRUE); + err = row_drop_table_for_mysql(table->name, trx, TRUE, FALSE); trx_commit_for_mysql(trx); ut_a(err == DB_SUCCESS); diff --git a/storage/xtradb/dict/dict0crea.cc b/storage/xtradb/dict/dict0crea.cc index 37ebdbae54a..b0a3263d097 100644 --- a/storage/xtradb/dict/dict0crea.cc +++ b/storage/xtradb/dict/dict0crea.cc @@ -1365,7 +1365,7 @@ dict_create_or_check_foreign_constraint_tables(void) ib_logf(IB_LOG_LEVEL_WARN, "Dropping incompletely created " "SYS_FOREIGN table."); - row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE); } if (sys_foreign_cols_err == DB_CORRUPTION) { @@ -1373,7 +1373,7 @@ dict_create_or_check_foreign_constraint_tables(void) "Dropping incompletely created " "SYS_FOREIGN_COLS table."); - row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE); } ib_logf(IB_LOG_LEVEL_WARN, @@ -1427,8 +1427,8 @@ dict_create_or_check_foreign_constraint_tables(void) ut_ad(err == DB_OUT_OF_FILE_SPACE || err == DB_TOO_MANY_CONCURRENT_TRXS); - row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE); - row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN", trx, TRUE, TRUE); + row_drop_table_for_mysql("SYS_FOREIGN_COLS", trx, TRUE, TRUE); if (err == DB_OUT_OF_FILE_SPACE) { err = DB_MUST_GET_MORE_FILE_SPACE; @@ -1852,7 +1852,7 @@ dict_create_or_check_sys_tablespace(void) ib_logf(IB_LOG_LEVEL_WARN, "Dropping incompletely created " "SYS_TABLESPACES table."); - row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE); + row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE, TRUE); } if (sys_datafiles_err == DB_CORRUPTION) { @@ -1860,7 +1860,7 @@ dict_create_or_check_sys_tablespace(void) "Dropping incompletely created " "SYS_DATAFILES table."); - row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE); + row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE, TRUE); } ib_logf(IB_LOG_LEVEL_INFO, @@ -1896,8 +1896,8 @@ dict_create_or_check_sys_tablespace(void) ut_a(err == DB_OUT_OF_FILE_SPACE || err == DB_TOO_MANY_CONCURRENT_TRXS); - row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE); - row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE); + row_drop_table_for_mysql("SYS_TABLESPACES", trx, TRUE, TRUE); + row_drop_table_for_mysql("SYS_DATAFILES", trx, TRUE, TRUE); if (err == DB_OUT_OF_FILE_SPACE) { err = DB_MUST_GET_MORE_FILE_SPACE; diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index fe97b9f7e1a..695e1d25dbe 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -1919,7 +1919,7 @@ func_exit: trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(table->name, trx, FALSE); + row_drop_table_for_mysql(table->name, trx, FALSE, TRUE); trx->error_state = DB_SUCCESS; } @@ -2071,7 +2071,7 @@ fts_create_index_tables_low( trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, TRUE); trx->error_state = DB_SUCCESS; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 0bedadc63d9..82e44fe5af0 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -11470,7 +11470,8 @@ ha_innobase::delete_table( /* Drop the table in InnoDB */ err = row_drop_table_for_mysql( - norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB); + norm_name, trx, thd_sql_command(thd) == SQLCOM_DROP_DB, + FALSE); if (err == DB_TABLE_NOT_FOUND @@ -11501,7 +11502,8 @@ ha_innobase::delete_table( #endif err = row_drop_table_for_mysql( par_case_name, trx, - thd_sql_command(thd) == SQLCOM_DROP_DB); + thd_sql_command(thd) == SQLCOM_DROP_DB, + FALSE); } } diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index 027d76317c4..a2f2a2e7371 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -488,6 +488,9 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: dictionary transaction handle */ bool drop_db,/*!< in: true=dropping whole database */ + ibool create_failed,/*!n_ref_count == 0); - return(row_drop_table_for_mysql(table->name, trx, false, false)); + return(row_drop_table_for_mysql(table->name, trx, false, false, false)); } /*********************************************************************//** diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 999bfbd401e..446237078c2 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -2400,7 +2400,7 @@ err_exit: dict_table_close(table, TRUE, FALSE); - row_drop_table_for_mysql(table->name, trx, FALSE); + row_drop_table_for_mysql(table->name, trx, FALSE, TRUE); if (commit) { trx_commit_for_mysql(trx); @@ -2560,7 +2560,7 @@ error_handling: trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); @@ -2637,7 +2637,7 @@ row_table_add_foreign_constraints( trx_rollback_to_savepoint(trx, NULL); - row_drop_table_for_mysql(name, trx, FALSE); + row_drop_table_for_mysql(name, trx, FALSE, TRUE); trx_commit_for_mysql(trx); @@ -2678,7 +2678,7 @@ row_drop_table_for_mysql_in_background( /* Try to drop the table in InnoDB */ - error = row_drop_table_for_mysql(name, trx, FALSE); + error = row_drop_table_for_mysql(name, trx, FALSE, FALSE); /* Flush the log to reduce probability that the .frm files and the InnoDB data dictionary get out-of-sync if the user runs @@ -3776,6 +3776,9 @@ row_drop_table_for_mysql( const char* name, /*!< in: table name */ trx_t* trx, /*!< in: transaction handle */ bool drop_db,/*!< in: true=dropping whole database */ + ibool create_failed,/*!foreign_table_name_lookup); - if (foreign->foreign_table != table && !ref_ok) { + /* We should allow dropping a referenced table if creating + that referenced table has failed for some reason. For example + if referenced table is created but it column types that are + referenced do not match. */ + if (foreign->foreign_table != table && + !create_failed && !ref_ok) { FILE* ef = dict_foreign_err_file; @@ -4507,7 +4515,7 @@ row_mysql_drop_temp_tables(void) table = dict_table_get_low(table_name); if (table) { - row_drop_table_for_mysql(table_name, trx, FALSE); + row_drop_table_for_mysql(table_name, trx, FALSE, FALSE); trx_commit_for_mysql(trx); } @@ -4676,7 +4684,7 @@ loop: goto loop; } - err = row_drop_table_for_mysql(table_name, trx, TRUE); + err = row_drop_table_for_mysql(table_name, trx, TRUE, FALSE); trx_commit_for_mysql(trx); if (err != DB_SUCCESS) { diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc index e2c3c0b949c..0243507ddfb 100644 --- a/storage/xtradb/trx/trx0roll.cc +++ b/storage/xtradb/trx/trx0roll.cc @@ -641,7 +641,7 @@ trx_rollback_active( "in recovery", table->name, trx->table_id); - err = row_drop_table_for_mysql(table->name, trx, TRUE); + err = row_drop_table_for_mysql(table->name, trx, TRUE, FALSE); trx_commit_for_mysql(trx); ut_a(err == DB_SUCCESS);