[Commits] e5aa8ea5255: MDEV-18139 ALTER IGNORE ... ADD FOREIGN KEY causes bogus error

sujatha sujatha.sivakumar at mariadb.com
Wed Apr 24 10:03:31 EEST 2019


revision-id: e5aa8ea52552759453fdd86eeab0007df1781b62 (mariadb-5.5.63-19-ge5aa8ea5255)
parent(s): 38b6dc5a3d11d9917c02ad10293807b5a0a4f5a0
author: Marko Mäkelä
committer: Marko Mäkelä
timestamp: 2019-04-23 17:56:43 +0300
message:

MDEV-18139 ALTER IGNORE ... ADD FOREIGN KEY causes bogus error

dict_create_foreign_constraints_low(): Tolerate the keywords
IGNORE and ONLINE between the keywords ALTER and TABLE.

We should really remove the hacky FOREIGN KEY constraint parser
from InnoDB.

---
 mysql-test/suite/innodb/r/foreign_key.result | 20 ++++++++++++++++++++
 mysql-test/suite/innodb/t/foreign_key.test   | 22 ++++++++++++++++++++++
 storage/innobase/dict/dict0dict.c            | 23 ++++++++++++++++++-----
 storage/xtradb/dict/dict0dict.c              | 23 ++++++++++++++++++-----
 4 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
new file mode 100644
index 00000000000..39f99513ee0
--- /dev/null
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -0,0 +1,20 @@
+#
+# MDEV-18630 Conditional jump or move depends on uninitialised value
+# in ib_push_warning / dict_create_foreign_constraints_low
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
+ERROR HY000: Can't create table 'test.#sql-temporary' (errno: 150)
+SHOW WARNINGS;
+Level	Code	Message
+Warning	150	Alter  table `test`.`t1` with foreign key constraint failed. Referenced table `test`.`t2` not found in the data dictionary near 'FOREIGN KEY (a) REFERENCES t2 (b)'.
+Error	1005	Can't create table 'test.#sql-temporary' (errno: 150)
+DROP TABLE t1;
+#
+# MDEV-18139 ALTER IGNORE ... ADD FOREIGN KEY causes bogus error
+#
+CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, KEY(f1)) ENGINE=InnoDB;
+CREATE TABLE t2 (f INT, KEY(f)) ENGINE=InnoDB;
+ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t2 (f);
+ALTER IGNORE TABLE t1 ADD FOREIGN KEY (f3) REFERENCES t1 (f1);
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
new file mode 100644
index 00000000000..281193d60ec
--- /dev/null
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -0,0 +1,22 @@
+--source include/have_innodb.inc
+
+--echo #
+--echo # MDEV-18630 Conditional jump or move depends on uninitialised value
+--echo # in ib_push_warning / dict_create_foreign_constraints_low
+--echo #
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
+--error ER_CANT_CREATE_TABLE
+ALTER IGNORE TABLE t1 ADD FOREIGN KEY (a) REFERENCES t2 (b);
+--replace_regex /#sql-[0-9_a-f-]*/#sql-temporary/
+SHOW WARNINGS;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-18139 ALTER IGNORE ... ADD FOREIGN KEY causes bogus error
+--echo #
+CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, KEY(f1)) ENGINE=InnoDB;
+CREATE TABLE t2 (f INT, KEY(f)) ENGINE=InnoDB;
+ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t2 (f);
+ALTER IGNORE TABLE t1 ADD FOREIGN KEY (f3) REFERENCES t1 (f1);
+DROP TABLE t1, t2;
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
index 588c2968b6a..fcb9a48e4c0 100644
--- a/storage/innobase/dict/dict0dict.c
+++ b/storage/innobase/dict/dict0dict.c
@@ -1,6 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -3787,6 +3788,9 @@ dict_create_foreign_constraints_low(
 		}
 
 		goto loop;
+	} else {
+		strncpy(create_name, name, sizeof create_name);
+		create_name[(sizeof create_name) - 1] = '\0';
 	}
 
 	if (table == NULL) {
@@ -3811,11 +3815,20 @@ dict_create_foreign_constraints_low(
 		goto loop;
 	}
 
-	ptr = dict_accept(cs, ptr, "TABLE", &success);
-
-	if (!success) {
-
-		goto loop;
+	orig = ptr;
+	for (;;) {
+		ptr = dict_accept(cs, ptr, "TABLE", &success);
+		if (success) {
+			break;
+		}
+		ptr = dict_accept(cs, ptr, "ONLINE", &success);
+		if (success) {
+			continue;
+		}
+		ptr = dict_accept(cs, ptr, "IGNORE", &success);
+		if (!success) {
+			goto loop;
+		}
 	}
 
 	/* We are doing an ALTER TABLE: scan the table name we are altering */
diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c
index 5da4509599e..12d3a600e54 100644
--- a/storage/xtradb/dict/dict0dict.c
+++ b/storage/xtradb/dict/dict0dict.c
@@ -1,6 +1,7 @@
 /*****************************************************************************
 
 Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -3921,6 +3922,9 @@ dict_create_foreign_constraints_low(
 		}
 
 		goto loop;
+	} else {
+		strncpy(create_name, name, sizeof create_name);
+		create_name[(sizeof create_name) - 1] = '\0';
 	}
 
 	if (table == NULL) {
@@ -3945,11 +3949,20 @@ dict_create_foreign_constraints_low(
 		goto loop;
 	}
 
-	ptr = dict_accept(cs, ptr, "TABLE", &success);
-
-	if (!success) {
-
-		goto loop;
+	orig = ptr;
+	for (;;) {
+		ptr = dict_accept(cs, ptr, "TABLE", &success);
+		if (success) {
+			break;
+		}
+		ptr = dict_accept(cs, ptr, "ONLINE", &success);
+		if (success) {
+			continue;
+		}
+		ptr = dict_accept(cs, ptr, "IGNORE", &success);
+		if (!success) {
+			goto loop;
+		}
 	}
 
 	/* We are doing an ALTER TABLE: scan the table name we are altering */


More information about the commits mailing list