summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-04-23 17:56:43 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-04-23 17:56:43 +0300
commite5aa8ea52552759453fdd86eeab0007df1781b62 (patch)
treee3fc289b2f0811cb10bc05f49ba806b35a9dd63e
parent38b6dc5a3d11d9917c02ad10293807b5a0a4f5a0 (diff)
downloadmariadb-git-e5aa8ea52552759453fdd86eeab0007df1781b62.tar.gz
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.
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result20
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test22
-rw-r--r--storage/innobase/dict/dict0dict.c23
-rw-r--r--storage/xtradb/dict/dict0dict.c23
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 */