Skip to content
Permalink
Browse files
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.
  • Loading branch information
dr-m committed Apr 23, 2019
1 parent 38b6dc5 commit e5aa8ea
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 10 deletions.
@@ -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;
@@ -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;
@@ -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 */
@@ -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 */

0 comments on commit e5aa8ea

Please sign in to comment.