summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2022-10-15 01:41:37 +0300
committerAleksey Midenkov <midenok@gmail.com>2022-10-15 01:41:37 +0300
commit6df00b8559347e090a07fc971a033419432fda27 (patch)
tree71714848c8c1afacccfa28bb3e56d305993b87d8
parentaabf07307497c8ed2089869f8f1d2210c06c1709 (diff)
downloadmariadb-git-6df00b8559347e090a07fc971a033419432fda27.tar.gz
MDEV-29783 ER_NO_SUCH_TABLE_IN_ENGINE after failed CREATE OR REPLACE with FK violation
If atomic C-O-R fails it reverts back to original table. When doing so InnoDB code checked old table for foreign key consistency and failed. The patch disables foreign key check when reverting to original table: they was created in previous statement and current statement has nothing to do with that. InnoDB part just disables any warnings in that case. The warnings was done when the foreign keys was created.
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result21
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test13
-rw-r--r--sql/sql_table.cc3
-rw-r--r--storage/innobase/row/row0mysql.cc8
4 files changed, 44 insertions, 1 deletions
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
index 6a151832c06..7a7e9625819 100644
--- a/mysql-test/suite/innodb/r/foreign_key.result
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -1100,3 +1100,24 @@ alter table t1 modify a bigint;
set foreign_key_checks = on;
create or replace table t1 (a int) engine=innodb;
drop tables t1, t2;
+#
+# MDEV-29783 ER_NO_SUCH_TABLE_IN_ENGINE after failed CREATE OR REPLACE with FK violation
+#
+create table t1 (a int, key (a)) engine=innodb;
+create table t2 (b int, foreign key (b) references t1 (a)) engine=innodb;
+set statement foreign_key_checks=off for alter table t1 modify a varchar(8);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(8) DEFAULT NULL,
+ KEY `a` (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+create or replace table t1 (c int) engine=innodb;
+ERROR HY000: Can't create table `test`.`./test/t1` (errno: 150 "Foreign key constraint is incorrectly formed")
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(8) DEFAULT NULL,
+ KEY `a` (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+drop table t2, t1;
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
index 8ceaf5ffcbc..f5259dda55c 100644
--- a/mysql-test/suite/innodb/t/foreign_key.test
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -1115,4 +1115,17 @@ set foreign_key_checks = on;
create or replace table t1 (a int) engine=innodb;
drop tables t1, t2;
+--echo #
+--echo # MDEV-29783 ER_NO_SUCH_TABLE_IN_ENGINE after failed CREATE OR REPLACE with FK violation
+--echo #
+create table t1 (a int, key (a)) engine=innodb;
+create table t2 (b int, foreign key (b) references t1 (a)) engine=innodb;
+set statement foreign_key_checks=off for alter table t1 modify a varchar(8);
+show create table t1;
+--error ER_CANT_CREATE_TABLE
+create or replace table t1 (c int) engine=innodb;
+show create table t1;
+# cleanup
+drop table t2, t1;
+
--source include/wait_until_count_sessions.inc
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 82f750b420f..1f075d7d088 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4531,7 +4531,10 @@ void HA_CREATE_INFO::finalize_ddl(THD *thd, bool roll_back)
debug_crash_here("ddl_log_create_fk_fail");
ddl_log_complete(ddl_log_state_rm);
debug_crash_here("ddl_log_create_fk_fail2");
+ ulonglong option_bits_save= thd->variables.option_bits;
+ thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
(void) ddl_log_revert(thd, ddl_log_state_create);
+ thd->variables.option_bits= option_bits_save;
debug_crash_here("ddl_log_create_fk_fail3");
}
else
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 7f5edb068db..24514af9b4d 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -2801,7 +2801,13 @@ row_rename_table_for_mysql(
fk_tables);
if (err != DB_SUCCESS) {
- if (old_is_tmp) {
+ if (old_is_tmp && fk == RENAME_FK &&
+ !trx->check_foreigns) {
+ /* Reverting atomic C-O-R from backup,
+ don't warn anything here. */
+ err = DB_SUCCESS;
+ break;
+ } else if (old_is_tmp) {
/* In case of copy alter, ignore the
loading of foreign key constraint
when foreign_key_check is disabled */