Skip to content
/ server Public
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions mysql-test/suite/innodb/r/foreign_key.result
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY fk1 (b) REFERENCES t1 (a))
ENGINE=InnoDB;
ALTER TABLE t2 DROP FOREIGN KEY fk1, DROP FOREIGN KEY fk1;
ERROR 42000: Can't DROP FOREIGN KEY `fk1`; check that it exists
DROP TABLE t2, t1;
CREATE TABLE t1 (f VARCHAR(256)) ENGINE=InnoDB;
SET SESSION FOREIGN_KEY_CHECKS = OFF;
Expand Down Expand Up @@ -1200,4 +1201,28 @@ set GLOBAL innodb_fast_shutdown=0;
# restart
ALTER TABLE t2 FORCE;
DROP TABLE t2, t1, t3;
#
# MDEV-19194 ASAN use-after-poison in
# fk_prepare_copy_alter_table upon dropping FK
#
CREATE TABLE t1(f1 INT NOT NULL, KEY(f1))ENGINE=InnoDB;
CREATE TABLE t2(f1 INT NOT NULL,
FOREIGN KEY `f1`(f1) REFERENCES t1(f1))ENGINE=InnoDB;
ALTER TABLE t2 DROP FOREIGN KEY f1, DROP FOREIGN KEY f1, ALGORITHM=COPY;
ERROR 42000: Can't DROP FOREIGN KEY `f1`; check that it exists
ALTER TABLE t2 DROP FOREIGN KEY f1, DROP FOREIGN KEY IF EXISTS f1, ALGORITHM=COPY;
Warnings:
Note 1091 Can't DROP FOREIGN KEY `f1`; check that it exists
ALTER TABLE t2 DROP FOREIGN KEY f1, ALGORITHM=COPY;
ERROR 42000: Can't DROP FOREIGN KEY `f1`; check that it exists
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS f1, ALGORITHM=COPY;
Warnings:
Note 1091 Can't DROP FOREIGN KEY `f1`; check that it exists
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS f1, DROP FOREIGN KEY f1, ALGORITHM=COPY;
ERROR 42000: Can't DROP FOREIGN KEY `f1`; check that it exists
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS f1, DROP FOREIGN KEY IF EXISTS f1, ALGORITHM=COPY;
Warnings:
Note 1091 Can't DROP FOREIGN KEY `f1`; check that it exists
Note 1091 Can't DROP FOREIGN KEY `f1`; check that it exists
DROP TABLE t2, t1;
# End of 10.6 tests
19 changes: 19 additions & 0 deletions mysql-test/suite/innodb/t/foreign_key.test
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ DROP TABLE t1;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY fk1 (b) REFERENCES t1 (a))
ENGINE=InnoDB;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t2 DROP FOREIGN KEY fk1, DROP FOREIGN KEY fk1;
DROP TABLE t2, t1;

Expand Down Expand Up @@ -1271,4 +1272,22 @@ set GLOBAL innodb_fast_shutdown=0;
ALTER TABLE t2 FORCE;
DROP TABLE t2, t1, t3;

--echo #
--echo # MDEV-19194 ASAN use-after-poison in
--echo # fk_prepare_copy_alter_table upon dropping FK
--echo #
CREATE TABLE t1(f1 INT NOT NULL, KEY(f1))ENGINE=InnoDB;
CREATE TABLE t2(f1 INT NOT NULL,
FOREIGN KEY `f1`(f1) REFERENCES t1(f1))ENGINE=InnoDB;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t2 DROP FOREIGN KEY f1, DROP FOREIGN KEY f1, ALGORITHM=COPY;
ALTER TABLE t2 DROP FOREIGN KEY f1, DROP FOREIGN KEY IF EXISTS f1, ALGORITHM=COPY;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t2 DROP FOREIGN KEY f1, ALGORITHM=COPY;
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS f1, ALGORITHM=COPY;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS f1, DROP FOREIGN KEY f1, ALGORITHM=COPY;
ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS f1, DROP FOREIGN KEY IF EXISTS f1, ALGORITHM=COPY;
DROP TABLE t2, t1;

--echo # End of 10.6 tests
52 changes: 52 additions & 0 deletions sql/sql_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9012,6 +9012,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{
Alter_drop *drop;
drop_it.rewind();
List<LEX_CSTRING> dropped_fk;
while ((drop=drop_it++)) {
switch (drop->type) {
case Alter_drop::KEY:
Expand Down Expand Up @@ -9041,7 +9042,18 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
{
if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
drop->name) == 0)
{
List_iterator<LEX_CSTRING> check_it(dropped_fk);
LEX_CSTRING *dropped_name;
while ((dropped_name = check_it++))
{
if (my_strcasecmp(system_charset_info, dropped_name->str,
f_key->foreign_id->str) == 0)
goto fk_not_found;
}
dropped_fk.push_back(f_key->foreign_id);
goto fk_found;
}
}
goto fk_not_found;
fk_found:
Expand Down Expand Up @@ -9336,6 +9348,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
when a foreign key has the same table as child and parent.
*/
List_iterator<FOREIGN_KEY_INFO> fk_parent_key_it(fk_parent_key_list);
List<FOREIGN_KEY_INFO> keys_to_remove;

while ((f_key= fk_parent_key_it++))
{
Expand All @@ -9358,7 +9371,26 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
&table->s->db) == 0) &&
(lex_string_cmp(table_alias_charset, f_key->foreign_table,
&table->s->table_name) == 0))
{
keys_to_remove.push_back(f_key);
break;
}
}
}

/* Remove the identified keys */
List_iterator<FOREIGN_KEY_INFO> remove_it(keys_to_remove);
while ((f_key = remove_it++))
{
fk_parent_key_it.rewind();
FOREIGN_KEY_INFO *fk;
while ((fk= fk_parent_key_it++))
{
if (fk == f_key)
{
fk_parent_key_it.remove();
break;
}
}
}

Expand Down Expand Up @@ -9432,6 +9464,7 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
by this ALTER TABLE.
*/
List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
keys_to_remove.empty();

while ((f_key= fk_key_it++))
{
Expand All @@ -9444,7 +9477,26 @@ static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
if ((drop->type == Alter_drop::FOREIGN_KEY) &&
(my_strcasecmp(system_charset_info, f_key->foreign_id->str,
drop->name) == 0))
{
keys_to_remove.push_back(f_key);
break;
}
}
}

/* Remove the identified keys */
List_iterator<FOREIGN_KEY_INFO> remove_it2(keys_to_remove);
while ((f_key = remove_it2++))
{
FOREIGN_KEY_INFO *fk;
fk_key_it.rewind();
while ((fk= fk_key_it++))
{
if (fk == f_key)
{
fk_key_it.remove();
break;
}
}
}

Expand Down