drop table if exists t_34455; create table t_34455 ( a int not null, foreign key (a) references t3 (a) match full match partial); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match partial)' at line 3 create table t_34455 ( a int not null, foreign key (a) references t3 (a) on delete set default match full); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 3 create table t_34455 ( a int not null, foreign key (a) references t3 (a) on update set default match full); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 3 create table t_34455 ( a int not null, foreign key (a) references t3 (a) on delete set default on delete set default); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete set default)' at line 4 create table t_34455 ( a int not null, foreign key (a) references t3 (a) on update set default on update set default); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update set default)' at line 4 create table t_34455 (a int not null); alter table t_34455 add foreign key (a) references t3 (a) match full match partial); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match partial)' at line 2 alter table t_34455 add foreign key (a) references t3 (a) on delete set default match full); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 2 alter table t_34455 add foreign key (a) references t3 (a) on update set default match full); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 2 alter table t_34455 add foreign key (a) references t3 (a) on delete set default on delete set default); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete set default)' at line 3 alter table t_34455 add foreign key (a) references t3 (a) on update set default on update set default); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update set default)' at line 3 drop table t_34455; # # WL#6929: Move FOREIGN KEY constraints to the global data dictionary # # Extra coverage of @@foreign_key_checks # SET @@foreign_key_checks= 0; CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY (b) REFERENCES non(a)); ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES non(a); DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY); CREATE TABLE t2(a INT PRIMARY KEY, b INT, FOREIGN KEY (b) REFERENCES t1(a)); DROP TABLE t1; DROP TABLE t2; SET @@foreign_key_checks= 1; CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY (b) REFERENCES non(a)); ERROR HY000: Failed to open the referenced table 'non' CREATE TABLE t1(a INT PRIMARY KEY, b INT REFERENCES non(a)); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES non(a); ERROR HY000: Failed to open the referenced table 'non' DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY); CREATE TABLE t2(a INT PRIMARY KEY, b INT, FOREIGN KEY (b) REFERENCES t1(a)); DROP TABLE t1; ERROR HY000: Cannot drop table 't1' referenced by a foreign key constraint 't2_ibfk_1' on table 't2'. DROP TABLE t2, t1; SET @@foreign_key_checks= DEFAULT; # Test coverage of identifier length related to foreign keys. # CREATE TABLE t1(a INT PRIMARY KEY); CREATE TABLE t2(a INT PRIMARY KEY, b INT); ALTER TABLE t2 ADD CONSTRAINT name567890123456789012345678901234567890123456789012345678901234 FOREIGN KEY name567890123456789012345678901234567890123456789012345678901234 (b) REFERENCES t1(a); SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `a` int(11) NOT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`a`), KEY `name567890123456789012345678901234567890123456789012345678901234` (`b`), CONSTRAINT `name567890123456789012345678901234567890123456789012345678901234` FOREIGN KEY (`b`) REFERENCES `t1` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = 't1'; CONSTRAINT_NAME name567890123456789012345678901234567890123456789012345678901234 DROP TABLE t2; CREATE TABLE t2(a INT PRIMARY KEY, b INT); ALTER TABLE t2 ADD FOREIGN KEY name5678901234567890123456789012345678901234567890123456789012345 (b) REFERENCES t1(a); ERROR 42000: Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long ALTER TABLE t2 ADD CONSTRAINT name5678901234567890123456789012345678901234567890123456789012345 FOREIGN KEY (b) REFERENCES t1(a); ERROR 42000: Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long DROP TABLE t2; CREATE TABLE t2(a INT PRIMARY KEY, b INT UNIQUE); ALTER TABLE t2 ADD FOREIGN KEY name5678901234567890123456789012345678901234567890123456789012345 (b) REFERENCES t1(a); ERROR 42000: Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long ALTER TABLE t2 ADD CONSTRAINT name5678901234567890123456789012345678901234567890123456789012345 FOREIGN KEY (b) REFERENCES t1(a); ERROR 42000: Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long DROP TABLE t2; DROP TABLE t1; CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY(b) REFERENCES name5678901234567890123456789012345678901234567890123456789012345.t2(a)); ERROR 42000: Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY(b) REFERENCES name5678901234567890123456789012345678901234567890123456789012345(a)); ERROR 42000: Incorrect table name 'name5678901234567890123456789012345678901234567890123456789012345' CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY(b) REFERENCES t2(name5678901234567890123456789012345678901234567890123456789012345)); ERROR 42000: Incorrect column name 'name5678901234567890123456789012345678901234567890123456789012345' SET @@foreign_key_checks= 0; CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY(b) REFERENCES name5678901234567890123456789012345678901234567890123456789012345.t2(a)); ERROR 42000: Identifier name 'name5678901234567890123456789012345678901234567890123456789012345' is too long CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY(b) REFERENCES name5678901234567890123456789012345678901234567890123456789012345(a)); ERROR 42000: Incorrect table name 'name5678901234567890123456789012345678901234567890123456789012345' CREATE TABLE t1(a INT PRIMARY KEY, b INT, FOREIGN KEY(b) REFERENCES t2(name5678901234567890123456789012345678901234567890123456789012345)); ERROR 42000: Incorrect column name 'name5678901234567890123456789012345678901234567890123456789012345' SET @@foreign_key_checks= DEFAULT; # # Bug#24666169: I_S.TABLE_CONSTRAINTS.CONSTRAINT_NAME IS NOT UPDATED # AFTER RENAME TABLE # SET @@foreign_key_checks= 1; # # Tests for FK name behavior. CREATE TABLE t1(c1 INT PRIMARY KEY); CREATE TABLE t2(c1 INT, FOREIGN KEY (c1) REFERENCES t1(c1)); ALTER TABLE t2 RENAME TO t3; SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( `c1` int(11) DEFAULT NULL, KEY `c1` (`c1`), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci INSERT INTO t3 VALUES(1); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`)) ALTER TABLE t3 RENAME TO t4, ALGORITHM= INPLACE; SHOW CREATE TABLE t4; Table Create Table t4 CREATE TABLE `t4` ( `c1` int(11) DEFAULT NULL, KEY `c1` (`c1`), CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci INSERT INTO t4 VALUES(1); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`)) ALTER TABLE t4 RENAME TO t5; SHOW CREATE TABLE t5; Table Create Table t5 CREATE TABLE `t5` ( `c1` int(11) DEFAULT NULL, KEY `c1` (`c1`), CONSTRAINT `t5_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci INSERT INTO t5 VALUES(1); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t5`, CONSTRAINT `t5_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`)) RENAME TABLE t5 to t6; SHOW CREATE TABLE t6; Table Create Table t6 CREATE TABLE `t6` ( `c1` int(11) DEFAULT NULL, KEY `c1` (`c1`), CONSTRAINT `t6_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci INSERT INTO t6 VALUES(1); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t6`, CONSTRAINT `t6_ibfk_1` FOREIGN KEY (`c1`) REFERENCES `t1` (`c1`)) DROP TABLE t6, t1; # # Tests of FK name generation CREATE TABLE t1(a INT PRIMARY KEY); CREATE TABLE t2(a INT, b INT, FOREIGN KEY(a) REFERENCES t1(a)); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_1 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_1 # Add FK ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_1 t2_ibfk_2 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_1 t2_ibfk_2 # Remove first FK and add a new FK. ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1; ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(a); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_2 t2_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_2 t2_ibfk_3 # Rename table in different ways. ALTER TABLE t2 RENAME TO t3; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't3' ORDER BY constraint_name; CONSTRAINT_NAME t3_ibfk_2 t3_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't3' ORDER BY constraint_name; constraint_name t3_ibfk_2 t3_ibfk_3 ALTER TABLE t3 RENAME TO t4, ALGORITHM= INPLACE; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't4' ORDER BY constraint_name; CONSTRAINT_NAME t4_ibfk_2 t4_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't4' ORDER BY constraint_name; constraint_name t4_ibfk_2 t4_ibfk_3 ALTER TABLE t4 RENAME TO t5; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't5' ORDER BY constraint_name; CONSTRAINT_NAME t5_ibfk_2 t5_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't5' ORDER BY constraint_name; constraint_name t5_ibfk_2 t5_ibfk_3 RENAME TABLE t5 TO t6; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't6' ORDER BY constraint_name; CONSTRAINT_NAME t6_ibfk_2 t6_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't6' ORDER BY constraint_name; constraint_name t6_ibfk_2 t6_ibfk_3 # Simulate dump+restore and test rename DROP TABLE t6; CREATE TABLE `t6` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, KEY `b` (`b`), KEY `a` (`a`), CONSTRAINT `t6_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`a`), CONSTRAINT `t6_ibfk_3` FOREIGN KEY (`a`) REFERENCES `t1` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; Warnings: Warning 1681 Integer display width is deprecated and will be removed in a future release. Warning 1681 Integer display width is deprecated and will be removed in a future release. SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't6' ORDER BY constraint_name; CONSTRAINT_NAME t6_ibfk_2 t6_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't6' ORDER BY constraint_name; constraint_name t6_ibfk_2 t6_ibfk_3 RENAME TABLE t6 TO t2; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_2 t2_ibfk_3 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_2 t2_ibfk_3 # Remove all FKs and add one back ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_2, DROP FOREIGN KEY t2_ibfk_3; ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(a); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_1 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_1 # Add a foreign key with close to generated name ALTER TABLE t2 ADD CONSTRAINT t3_ibfk_2 FOREIGN KEY(b) REFERENCES t1(a); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_1 t3_ibfk_2 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_1 t3_ibfk_2 # Then rename so that the given name now matches a generated name RENAME TABLE t2 TO t3; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't3' ORDER BY constraint_name; CONSTRAINT_NAME t3_ibfk_1 t3_ibfk_2 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't3' ORDER BY constraint_name; constraint_name t3_ibfk_1 t3_ibfk_2 # Finally rename it again. The given name is now seen as generated and renamed. RENAME TABLE t3 TO t4; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't4' ORDER BY constraint_name; CONSTRAINT_NAME t4_ibfk_1 t4_ibfk_2 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't4' ORDER BY constraint_name; constraint_name t4_ibfk_1 t4_ibfk_2 DROP TABLE t4; # Make a foreign key with given name matching a generated name CREATE TABLE t2(a INT, b INT); ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_1 FOREIGN KEY(a) REFERENCES t1(a); ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME t2_ibfk_1 t2_ibfk_2 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name t2_ibfk_1 t2_ibfk_2 DROP TABLE t2; # Test FK name case sensitivity CREATE TABLE t2(a INT, b INT); ALTER TABLE t2 ADD CONSTRAINT FK FOREIGN KEY(a) REFERENCES t1(a); SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2' ORDER BY constraint_name; CONSTRAINT_NAME FK SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't2' ORDER BY constraint_name; constraint_name FK ALTER TABLE t2 ADD CONSTRAINT fk FOREIGN KEY(b) REFERENCES t1(a); ERROR 42000: Duplicate key name 'fk' ALTER TABLE t2 DROP FOREIGN KEY FK; # Name matching generated name, but different case. ALTER TABLE t2 ADD CONSTRAINT T2_IBFK_1 FOREIGN KEY(a) REFERENCES t1(a); ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a); ERROR HY000: Duplicate foreign key constraint name 't2_ibfk_1' ALTER TABLE t2 DROP FOREIGN KEY T2_IBFK_1; DROP TABLE t2; # Check long FK generated names due to long table names. CREATE TABLE t2 (a INT, FOREIGN KEY (a) REFERENCES t1(a)); RENAME TABLE t2 TO t123456789012345678901234567890123456789012345678901234567; ERROR 42000: Identifier name 't123456789012345678901234567890123456789012345678901234567_ibfk_1' is too long RENAME TABLE t2 TO t12345678901234567890123456789012345678901234567890123456; SELECT constraint_name FROM information_schema.referential_constraints WHERE table_name = 't12345678901234567890123456789012345678901234567890123456' ORDER BY constraint_name; CONSTRAINT_NAME t12345678901234567890123456789012345678901234567890123456_ibfk_1 SELECT constraint_name FROM information_schema.table_constraints WHERE table_name = 't12345678901234567890123456789012345678901234567890123456' ORDER BY constraint_name; constraint_name t12345678901234567890123456789012345678901234567890123456_ibfk_1 DROP TABLE t12345678901234567890123456789012345678901234567890123456; CREATE TABLE t123456789012345678901234567890123456789012345678901234567( a INT, FOREIGN KEY (a) REFERENCES t1(a)); ERROR 42000: Identifier name 't123456789012345678901234567890123456789012345678901234567_ibfk_1' is too long CREATE TABLE t123456789012345678901234567890123456789012345678901234567890123( a INT, CONSTRAINT fk FOREIGN KEY (a) REFERENCES t1(a)); DROP TABLE t123456789012345678901234567890123456789012345678901234567890123; DROP TABLE t1; # FK Referencing virtual column CREATE TABLE t1(a INT PRIMARY KEY, b INT GENERATED ALWAYS AS (a+1) VIRTUAL UNIQUE); CREATE TABLE t2(a INT, FOREIGN KEY (a) REFERENCES t1(b)); ERROR HY000: Foreign key 't2_ibfk_1' uses virtual column 'b' which is not supported. CREATE TABLE t2(a INT); ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(b); ERROR HY000: Foreign key 't2_ibfk_1' uses virtual column 'b' which is not supported. DROP TABLE t1, t2; # FK on generated stored column CREATE TABLE t1(a INT PRIMARY KEY); CREATE TABLE t2(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE); CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (b) REFERENCES t1(a)); ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a); ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1; DROP TABLE t3; CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (b) REFERENCES t1(a) ON UPDATE CASCADE); ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a generated column. ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a) ON UPDATE CASCADE; ERROR HY000: Cannot define foreign key with ON UPDATE CASCADE clause on a generated column. CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (b) REFERENCES t1(a) ON DELETE SET NULL); ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a generated column. ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a) ON DELETE SET NULL; ERROR HY000: Cannot define foreign key with ON DELETE SET NULL clause on a generated column. CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (b) REFERENCES t1(a) ON UPDATE SET NULL); ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a generated column. ALTER TABLE t2 ADD FOREIGN KEY(b) REFERENCES t1(a) ON UPDATE SET NULL; ERROR HY000: Cannot define foreign key with ON UPDATE SET NULL clause on a generated column. # FK on Base column of generated stored column. CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (a) REFERENCES t1(a)); ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(a); ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1; DROP TABLE t3; CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (a) REFERENCES t1(a) ON UPDATE CASCADE); ERROR HY000: Cannot add foreign key constraint ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(a) ON UPDATE CASCADE; ERROR HY000: Cannot add foreign key constraint CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (a) REFERENCES t1(a) ON DELETE SET NULL); ERROR HY000: Cannot add foreign key constraint ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(a) ON DELETE SET NULL; ERROR HY000: Cannot add foreign key constraint CREATE TABLE t3(a INT, b INT GENERATED ALWAYS AS (a+1) STORED UNIQUE, FOREIGN KEY (a) REFERENCES t1(a) ON UPDATE SET NULL); ERROR HY000: Cannot add foreign key constraint ALTER TABLE t2 ADD FOREIGN KEY(a) REFERENCES t1(a) ON UPDATE SET NULL; ERROR HY000: Cannot add foreign key constraint DROP TABLE t2, t1; # FK on virtual column not supported. CREATE TABLE t1(a INT PRIMARY KEY); CREATE TABLE t2(a INT, b INT GENERATED ALWAYS AS (a+1) VIRTUAL UNIQUE, FOREIGN KEY(b) REFERENCES t1(a)); ERROR HY000: Foreign key 't2_ibfk_1' uses virtual column 'b' which is not supported. CREATE TABLE t2(a INT, b INT GENERATED ALWAYS AS (a+1) VIRTUAL UNIQUE); ALTER TABLE t2 ADD FOREIGN KEY (b) REFERENCES t1(a); ERROR HY000: Foreign key 't2_ibfk_1' uses virtual column 'b' which is not supported. DROP TABLE t2; CREATE TABLE t2(a INT, b INT, FOREIGN KEY(b) REFERENCES t1(a)); ALTER TABLE t2 MODIFY COLUMN b INT GENERATED ALWAYS AS (a+1) VIRTUAL; ERROR HY000: 'Changing the STORED status' is not supported for generated columns. DROP TABLE t2, t1; # Trying to drop columns used in multi-column FKs. CREATE TABLE t1(a INT PRIMARY KEY, b INT, INDEX(a, b)); CREATE TABLE t2(a INT, b INT, FOREIGN KEY(a, b) REFERENCES t1(a, b)); ALTER TABLE t2 DROP COLUMN a; ERROR HY000: Cannot drop column 'a': needed in a foreign key constraint 't2_ibfk_1' ALTER TABLE t2 DROP COLUMN b; ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 't2_ibfk_1' DROP TABLE t2; # Use explicitly named index to check where index name is != column name. CREATE TABLE t2(a INT, b INT, INDEX idx(a, b), FOREIGN KEY(a, b) REFERENCES t1(a, b)); ALTER TABLE t2 DROP COLUMN a; ERROR HY000: Cannot drop column 'a': needed in a foreign key constraint 't2_ibfk_1' ALTER TABLE t2 DROP COLUMN b; ERROR HY000: Cannot drop column 'b': needed in a foreign key constraint 't2_ibfk_1' DROP TABLE t2, t1; # Index with prefix cannot be used for supporting FK. CREATE TABLE t1 (PK VARCHAR(100) PRIMARY KEY); CREATE TABLE t2 (FK VARCHAR(100), FOREIGN KEY(FK) REFERENCES t1 (PK), KEY(FK)); ALTER TABLE t2 DROP INDEX FK, ADD INDEX FK2(FK(10)); ERROR HY000: Cannot drop index 'FK': needed in a foreign key constraint DROP TABLE t2, t1; # Bug#25817660: Combination of virtual index, foreign key and trigger # result in assert failure CREATE TABLE t1(fld1 INT NOT NULL PRIMARY KEY); CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a:=0; CREATE TABLE t2(fld1 INT NOT NULL, fld2 INT AS (fld1) VIRTUAL, KEY(fld2), FOREIGN KEY(fld1) REFERENCES t1(fld1) ON UPDATE CASCADE); INSERT INTO t1 VALUES(1); INSERT INTO t2 VALUES(1, DEFAULT); UPDATE t1 SET fld1= 2; SELECT * FROM t1; fld1 2 SELECT * FROM t2; fld1 fld2 2 2 # The same test but with server restart before UPDATE. # Triggers different code path in InnoDB which was not # covered by original fix for the bug. # restart UPDATE t1 SET fld1= 3; SELECT * FROM t1; fld1 3 SELECT * FROM t2; fld1 fld2 3 3 DROP TABLE t2; DROP TABLE t1; # # Bug#20021917: WORK AROUND FOR CHARSET CONVERSION WITH FKS CAN # RESULT IN WRONG DATA # CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) UNIQUE); CREATE TABLE t2 (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), fname VARCHAR(100), FOREIGN KEY (fname) REFERENCES t1 (name) ON UPDATE CASCADE ON DELETE CASCADE); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, `fname` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fname` (`fname`), CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fname`) REFERENCES `t1` (`name`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ALTER TABLE t2 CONVERT TO CHARACTER SET latin1; ERROR HY000: Referencing column 'fname' and referenced column 'name' in foreign key constraint 't2_ibfk_1' are incompatible. SET foreign_key_checks= OFF; ALTER TABLE t2 CONVERT TO CHARACTER SET latin1; SET foreign_key_checks= ON; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, `fname` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fname` (`fname`), CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fname`) REFERENCES `t1` (`name`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=latin1 INSERT INTO t1(name) VALUES ('test1'); INSERT INTO t2(name, fname) VALUES ('test1', 'test1'); UPDATE t1 SET name=CONCAT('St', UNHEX('C3A5') ,'le') WHERE name = 'test1'; # Should not get any rows here SELECT t1.name, t2.fname FROM t1, t2 WHERE t1.name <> t2.fname; name fname Ståle StÃ¥le DROP TABLE t2; DROP TABLE t1; # # WL#6049: Meta-data locking for FOREIGN KEY tables # # Test case to check MDL on tables related by FK constraints. # CREATE TABLE grandparent (gpf1 INT PRIMARY KEY, gpf2 INT); INSERT INTO grandparent VALUES (1,10), (2,20); CREATE TABLE parent ( pf1 INT PRIMARY KEY, pf2 INT, sleep_dummy INT, CONSTRAINT pc1 FOREIGN KEY (pf2) REFERENCES grandparent (gpf1) ON DELETE NO ACTION ON UPDATE NO ACTION); INSERT INTO parent VALUES (1,1,0), (2,2,0); CREATE TABLE child ( cf1 INT PRIMARY KEY, cf2 INT, CONSTRAINT cc1 FOREIGN KEY (cf2) REFERENCES parent (pf1) ON DELETE NO ACTION ON UPDATE NO ACTION); INSERT INTO child VALUES (1,1), (2,2); connect con_A,localhost,root,,test; SET @@session.lock_wait_timeout= 1; UPDATE parent SET pf2= 2, sleep_dummy= SLEEP(2); connection default; set @conA_id = ; # Waiting for connection A to start udpate SET @@session.lock_wait_timeout= 1; # Updates not invoving the FK related column should succeed UPDATE grandparent SET gpf2= 4; UPDATE grandparent SET gpf2= 100 * gpf1; # DDL on child will have conflicting locks. ALTER TABLE child ADD COLUMN (i INT); ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@session.lock_wait_timeout= DEFAULT; connection con_A; disconnect con_A; connection default; DROP TABLE child; DROP TABLE parent; DROP TABLE grandparent; # # Systemic test coverage for metadata locks related to foreign # keys acquired by various DDL statements. # # Also provides coverage for data-dictionary cache invalidation # and cases when we fail to acquire necessary locks. SET @old_lock_wait_timeout= @@lock_wait_timeout; connect con1, localhost, root,,; connect con2, localhost, root,,; SET @old_lock_wait_timeout= @@lock_wait_timeout; connection default; # # 1) CREATE TABLE # # 1.1) CREATE TABLE must acquire X lock on parent table # (if table doesn't exist). CREATE TABLE parent (pk INT PRIMARY KEY); connection con1; BEGIN; SELECT * FROM parent; pk connection default; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk));; connection con1; # Wait until CREATE TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap CREATE TABLE # 1.2) CREATE TABLE for existing table should not acquire X lock # parent table connection con1; BEGIN; SELECT * FROM parent; pk connection default; CREATE TABLE IF NOT EXISTS child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); Warnings: Note 1050 Table 'child' already exists connection con1; COMMIT; connection default; DROP TABLE child; # 1.3) CREATE TABLE which acquires lock on parent table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE parent; # 1.4) CREATE TABLE which adds parent to orphan child must acquire X # on child table. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; CREATE TABLE parent (pk INT PRIMARY KEY);; connection con1; # Wait until CREATE TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap CREATE TABLE # 1.5) CREATE TABLE for existing table must not acquire X lock # on child table connection con1; BEGIN; SELECT * FROM child; fk connection default; CREATE TABLE IF NOT EXISTS parent (pk INT PRIMARY KEY); Warnings: Note 1050 Table 'parent' already exists connection con1; COMMIT; connection default; SET FOREIGN_KEY_CHECKS=0; DROP TABLE parent; SET FOREIGN_KEY_CHECKS=1; # 1.6) CREATE TABLE which acquires lock on child table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; CREATE TABLE parent (pk INT PRIMARY KEY); ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child; # 1.7) CREATE TABLE which adds FK should invalidate entries # in TC/TDC and DD caches for the parent table. CREATE TABLE parent (pk INT PRIMARY KEY); SELECT * FROM parent; pk connection con1; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE); connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquired SNRW lock on child table. SELECT * FROM child;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk connection default; DROP TABLES child, parent; # # 2) CREATE TABLE ... LIKE # # 2.1) CREATE TABLE ... LIKE doesn't copy foreign keys # so it should not any locks on FK parent tables. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); connection con1; LOCK TABLES parent WRITE; connection default; CREATE TABLE child2 LIKE child; connection con1; UNLOCK TABLES; connection default; # 2.2) CREATE TABLE LIKE which adds parent to orphan child must # acquire X on child table. SET FOREIGN_KEY_CHECKS=0; DROP TABLES child2, parent; SET FOREIGN_KEY_CHECKS=1; CREATE TABLE parent_source (pk INT PRIMARY KEY); connection con1; BEGIN; SELECT * FROM child; fk connection default; CREATE TABLE parent LIKE parent_source;; connection con1; # Wait until CREATE TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap CREATE TABLE # 2.3) CREATE TABLE LIKE for existing table must not acquire X lock # on child table connection con1; BEGIN; SELECT * FROM child; fk connection default; CREATE TABLE IF NOT EXISTS parent LIKE parent_source; Warnings: Note 1050 Table 'parent' already exists connection con1; COMMIT; connection default; SET FOREIGN_KEY_CHECKS=0; DROP TABLE parent; SET FOREIGN_KEY_CHECKS=1; # 2.4) CREATE TABLE LIKE which acquires lock on child table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; CREATE TABLE IF NOT EXISTS parent LIKE parent_source; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child, parent_source; # # 3) CREATE TABLE ... SELECT # # 3.1) CREATE TABLE ... SELECT must start by acquiring SU lock on parent # table (if table doesn't exist). CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE source (fk INT); INSERT INTO source VALUES (NULL); connection con1; BEGIN; SELECT * FROM source FOR UPDATE; fk NULL connection default; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)) SELECT fk FROM source;; connection con1; # Wait until CREATE TABLE is blocked by con1 because of row locks. # Demonstrate that CREATE TABLE holds SU lock on parent # which allows DML but not DDL. INSERT INTO parent VALUES (1); connection con2; SET @@lock_wait_timeout= 1; ALTER TABLE parent ADD COLUMN a INT; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; # Resume CREATE TABLE. COMMIT; connection default; # Reap CREATE TABLE DROP TABLES child, source; # 3.2) CREATE TABLE ... SELECT should upgrade SU lock on parent to X # before commit (i.e eventually X lock should be acquired). connection con1; BEGIN; SELECT * FROM parent; pk 1 connection default; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)) SELECT NULL AS fk;; connection con1; # Wait until CREATE TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap CREATE TABLE # 3.3) CREATE TABLE ... SELECT for existing table should not acquire # any locks on parent table. connection con1; CREATE TABLE parent2 (pk INT PRIMARY KEY); LOCK TABLE parent2 WRITE; connection default; CREATE TABLE IF NOT EXISTS child (fk INT, FOREIGN KEY (fk) REFERENCES parent2(pk)) SELECT NULL AS fk; Warnings: Note 1050 Table 'child' already exists connection con1; UNLOCK TABLES; connection default; DROP TABLE child; DROP TABLE parent2; # 3.4) CREATE TABLE ... SELECT which tries to acquire SU lock on parent # table and fails due to lock timeout. connection con1; LOCK TABLE parent WRITE; connection default; SET @@lock_wait_timeout= 1; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)) SELECT NULL AS fk; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; UNLOCK TABLES; # 3.5) CREATE TABLE ... SELECT which tries to upgrade to X lock on # parent table and fails due to lock timeout. BEGIN; SELECT * FROM parent; pk 1 connection default; SET @@lock_wait_timeout= 1; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)) SELECT NULL AS fk; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE parent; # 3.6) CREATE TABLE ... SELECT which adds parent to orphan child must # acquire X on child table. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; CREATE TABLE parent (pk INT PRIMARY KEY) SELECT 1 AS pk;; connection con1; # Wait until CREATE TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap CREATE TABLE # 3.7) CREATE TABLE ... SELECT for existing table must not # acquire X lock on child table connection con1; BEGIN; SELECT * FROM child; fk connection default; CREATE TABLE IF NOT EXISTS parent (pk INT PRIMARY KEY) SELECT 1 AS pk; Warnings: Note 1050 Table 'parent' already exists connection con1; COMMIT; connection default; SET FOREIGN_KEY_CHECKS=0; DROP TABLE parent; SET FOREIGN_KEY_CHECKS=1; # 3.8) CREATE TABLE ... SELECT which acquires lock on child table # and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; CREATE TABLE parent (pk INT PRIMARY KEY) SELECT 1 AS pk; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child; # 3.9) CREATE TABLE ... SELECT which adds FK should invalidate entries # in TC/TDC and DD caches for the parent table. CREATE TABLE parent (pk INT PRIMARY KEY); SELECT * FROM parent; pk connection con1; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE) SELECT NULL AS fk; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquired SNRW lock on child table. SELECT * FROM child;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk NULL connection default; DROP TABLES child, parent; # # 4) DROP TABLES # # 4.1) DROP TABLES must acquire X lock on parent table for FKs # when child is dropped. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); connection con1; BEGIN; SELECT * FROM parent; pk connection default; DROP TABLES child;; connection con1; # Wait until DROP TABLES is blocked by con1 and then resume it. COMMIT; connection default; # Reap DROP TABLES CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); # 4.2) DROP TABLES which acquires lock on parent table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; DROP TABLES child; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 4.3) DROP TABLES which tries to remove parent table must acquire X # lock on child table. connection con1; BEGIN; SELECT * FROM child; fk connection default; DROP TABLES parent;; connection con1; # Wait until DROP TABLES is blocked by con1 and then resume it. COMMIT; connection default; # Reap DROP TABLES ERROR HY000: Cannot drop table 'parent' referenced by a foreign key constraint 'child_ibfk_1' on table 'child'. # 4.4) DROP TABLES which acquires lock on child table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; DROP TABLES parent; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 4.5) DROP TABLES which deletes child should invalidate entries # in TC/TDC and DD caches for the parent table. DROP TABLES child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE); SELECT * FROM parent; pk connection con1; DROP TABLES child; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and avoid acquiring SNRW lock on child table. SELECT * FROM child; ERROR 42S02: Table 'test.child' doesn't exist connection default; UNLOCK TABLES; DROP TABLES parent; # # 5) RENAME TABLES # # 5.1) RENAME TABLES must acquire X lock on parent table for FKs # when child is renamed. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); connection con1; BEGIN; SELECT * FROM parent; pk connection default; RENAME TABLES child TO child1;; connection con1; # Wait until RENAME TABLES is blocked by con1 and then resume it. COMMIT; connection default; # Reap RENAME TABLES RENAME TABLES child1 TO child; # 5.2) RENAME TABLES which acquires lock on parent table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; RENAME TABLES child TO child1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 5.3) RENAME TABLES which tries to rename parent table must acquire X # lock on child table. connection con1; BEGIN; SELECT * FROM child; fk connection default; RENAME TABLES parent TO parent1;; connection con1; # Wait until RENAME TABLES is blocked by con1 and then resume it. COMMIT; connection default; # Reap RENAME TABLES RENAME TABLES parent1 TO parent; # 5.4) RENAME TABLES which acquires lock on child table and fails # due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; RENAME TABLES parent TO parent1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 5.5) RENAME TABLES which adds parent table for orphan child # must acquire X lock on this child table. connection default; DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; RENAME TABLES parent TO parent1;; connection con1; # Wait until RENAME TABLES is blocked by con1 and then resume it. COMMIT; connection default; # Reap RENAME TABLES RENAME TABLES parent1 TO parent; # 5.6) RENAME TABLES which acquires lock on orphan child table # and fails due to timeout. DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; RENAME TABLES parent TO parent1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE); # 5.7) RENAME TABLES on the child table should invalidate entries # in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk connection con1; RENAME TABLES child TO child1; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquire SNRW lock on new child table name. SELECT * FROM child1;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk connection default; DROP TABLES child1, parent; # # 6) Simple ALTER TABLE ... RENAME # # 6.1) ALTER TABLE ... RENAME must acquire X lock on parent table # for FKs when child is renamed. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); connection con1; BEGIN; SELECT * FROM parent; pk connection default; ALTER TABLE child RENAME TO child1;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES child1 TO child; # 6.2) ALTER TABLE ... RENAME which acquires lock on parent table and # fails due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child RENAME TO child1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 6.3) ALTER TABLE ... RENAME which tries to rename parent table must # acquire X lock on child table. connection con1; BEGIN; SELECT * FROM child; fk connection default; ALTER TABLE parent RENAME TO parent1;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES parent1 TO parent; # 6.4) ALTER TABLE ... RENAME which acquires lock on child table and # fails due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME TO parent1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 6.5) ALTER TABLE ... RENAME which adds parent table for orphan child # must acquire X lock on this child table. connection default; DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; ALTER TABLE parent RENAME TO parent1;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES parent1 TO parent; # 6.6) ALTER TABLE ... RENAME which acquires lock on orphan child table # and fails due to timeout. DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME TO parent1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE); # 6.7) ALTER TABLE ... RENAME on the child table should invalidate # entries in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk connection con1; ALTER TABLE child RENAME TO child1; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquire SNRW lock on new child table name. SELECT * FROM child1;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk connection default; DROP TABLES child1, parent; # # 7) ALTER TABLE ... INPLACE # # 7.1) ALTER TABLE ... ADD FOREIGN KEY ... INPLACE must start by # acquiring SU lock on parent table. # # This test uses debug_sync feature so resides in foreign_key_debug.test # # 7.2) ALTER TABLE ... ADD FOREIGN KEY ... INPLACE should upgrade SU # lock on parent to X before commit (i.e eventually X lock should # be acquired). CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT); connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET FOREIGN_KEY_CHECKS=0; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=INPLACE;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE SET FOREIGN_KEY_CHECKS=1; ALTER TABLE child DROP FOREIGN KEY fk; # 7.3) ALTER TABLE ... ADD FOREIGN KEY ... INPLACE which tries to # acquire SU lock on parent table and fails due to lock timeout. connection con1; LOCK TABLE parent WRITE; connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; UNLOCK TABLES; # 7.4) ALTER TABLE ... ADD FOREIGN KEY ... INPLACE which tries to # upgrade to X lock on parent table and fails due to lock timeout. BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; SET FOREIGN_KEY_CHECKS=0; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET FOREIGN_KEY_CHECKS=1; SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 7.5) ALTER TABLE ... ADD FOREIGN KEY ... INPLACE should invalidate # entries in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk connection con1; SET FOREIGN_KEY_CHECKS=0; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE, ALGORITHM=INPLACE; SET FOREIGN_KEY_CHECKS=1; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquired SNRW lock on child table. SELECT * FROM child;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk # 7.6) ALTER TABLE ... DROP FOREIGN KEY ... INPLACE should acquire # lock on parent to X before commit. connection con1; BEGIN; SELECT * FROM parent; pk connection default; ALTER TABLE child DROP FOREIGN KEY fk, ALGORITHM=INPLACE;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE; # 7.7) ALTER TABLE ... DROP FOREIGN KEY ... INPLACE which tries to # upgrade to X lock on parent table and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child DROP FOREIGN KEY fk, ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 7.8) ALTER TABLE ... DROP FOREIGN KEY ... INPLACE should invalidate entries # in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk connection con1; ALTER TABLE child DROP FOREIGN KEY fk, ALGORITHM=INPLACE; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and avoid acquiring SNRW lock on child table. SELECT * FROM child; fk connection default; UNLOCK TABLES; # 7.9) ALTER TABLE ... INPLACE which changes parent key must acquire X # lock on child table. DROP TABLES child, parent; CREATE TABLE parent (pk INT NOT NULL, UNIQUE u(pk)); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); connection con1; BEGIN; SELECT * FROM child; fk connection default; ALTER TABLE parent RENAME KEY u TO u1, ALGORITHM=INPLACE;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE # 7.10) ALTER TABLE ... INPLACE which changes parent key, so tries to # acquire X lock on child table, but fails due to timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME KEY u1 TO u, ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 7.11) ALTER TABLE ... RENAME ... INPLACE must acquire X lock on # parent table for FKs when child is renamed. connection con1; BEGIN; SELECT * FROM parent; pk connection default; ALTER TABLE child RENAME TO child1, ADD COLUMN a INT, ALGORITHM=INPLACE;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES child1 TO child; # 7.12) ALTER TABLE ... RENAME ... INPLACE which acquires lock on # parent table and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child RENAME TO child1, ADD COLUMN b INT, ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 7.13) ALTER TABLE ... RENAME ... INPLACE which tries to rename parent # table must acquire X lock on child table. connection con1; BEGIN; SELECT * FROM child; fk a connection default; ALTER TABLE parent RENAME TO parent1, ADD COLUMN a INT, ALGORITHM=INPLACE;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES parent1 TO parent; # 7.14) ALTER TABLE ... RENAME ... INPLACE which acquires lock on child # table and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk a connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME TO parent1, ADD COLUMN b INT, ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 7.15) ALTER TABLE ... RENAME ... INPLACE which adds parent table for # orphan child must acquire X lock on this child table. connection default; DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; ALTER TABLE parent RENAME TO parent1, ADD COLUMN c INT, ALGORITHM=INPLACE;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES parent1 TO parent; # 7.16) ALTER TABLE ... RENAME ... INPLACE which acquires lock on # orphan child table and fails due to timeout. DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME TO parent1, ADD COLUMN d INT, ALGORITHM=INPLACE; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE); # 7.17) ALTER TABLE ... RENAME ... INPLACE on the child table should # invalidate entries in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk a c connection con1; ALTER TABLE child RENAME TO child1, ADD COLUMN a INT, ALGORITHM=INPLACE; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquire SNRW lock on new child table name. SELECT * FROM child1;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk a connection default; DROP TABLES child1, parent; # # 8) ALTER TABLE ... COPY # # 8.1) ALTER TABLE ... ADD FOREIGN KEY ... COPY must start by # acquiring SU lock on parent table. # 8.1') ALTER TABLE ... ADD FOREIGN KEY ... COPY due to workaround # must upgrade SU lock on parent table SRO lock. # # These tests use debug_sync feature so reside in foreign_key_debug.test # # 8.2) ALTER TABLE ... ADD FOREIGN KEY ... COPY should upgrade SU (SRO) # lock on parent to X before commit (i.e eventually X lock should # be acquired). CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT); connection con1; BEGIN; SELECT * FROM parent; pk connection default; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=COPY;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE ALTER TABLE child DROP FOREIGN KEY fk; # 8.3) ALTER TABLE ... ADD FOREIGN KEY ... COPY which tries to # acquire SU lock on parent table and fails due to lock timeout. connection con1; LOCK TABLE parent WRITE; connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; UNLOCK TABLES; # 8.3') ALTER TABLE ... ADD FOREIGN KEY ... COPY which due to workaround # tries to upgrade SU lock on parent table to SRO and fails due to # lock timeout. connection con1; BEGIN; DELETE FROM parent; connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 8.4) ALTER TABLE ... ADD FOREIGN KEY ... COPY which tries to # upgrade to X lock on parent table and fails due to lock timeout. BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk), ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 8.5) ALTER TABLE ... ADD FOREIGN KEY ... COPY should invalidate # entries in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk connection con1; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE, ALGORITHM=COPY; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquired SNRW lock on child table. SELECT * FROM child;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk # 8.6) ALTER TABLE ... DROP FOREIGN KEY ... COPY should acquire # lock on parent to X before commit. connection con1; BEGIN; SELECT * FROM parent; pk connection default; ALTER TABLE child DROP FOREIGN KEY fk, ALGORITHM=COPY;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE; # 8.7) ALTER TABLE ... DROP FOREIGN KEY ... COPY which tries to # upgrade to X lock on parent table and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child DROP FOREIGN KEY fk, ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 8.8) ALTER TABLE ... DROP FOREIGN KEY ... COPY should invalidate entries # in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk connection con1; ALTER TABLE child DROP FOREIGN KEY fk, ALGORITHM=COPY; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and avoid acquiring SNRW lock on child table. SELECT * FROM child; fk connection default; UNLOCK TABLES; # 8.9) ALTER TABLE ... COPY which changes parent key must acquire X # lock on child table. DROP TABLES child, parent; CREATE TABLE parent (pk INT NOT NULL, UNIQUE u(pk)); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); connection con1; BEGIN; SELECT * FROM child; fk connection default; ALTER TABLE parent RENAME KEY u TO u1, ALGORITHM=COPY;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE # 8.10) ALTER TABLE ... COPY which changes parent key, so tries to # acquire X lock on child table, but fails due to timeout. connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME KEY u1 TO u, ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 8.11) ALTER TABLE ... RENAME ... COPY must acquire X lock on # parent table for FKs when child is renamed. connection con1; BEGIN; SELECT * FROM parent; pk connection default; ALTER TABLE child RENAME TO child1, ADD COLUMN a INT, ALGORITHM=COPY;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES child1 TO child; # 8.12) ALTER TABLE ... RENAME ... COPY which acquires lock on # parent table and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM parent; pk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE child RENAME TO child1, ADD COLUMN b INT, ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 8.13) ALTER TABLE ... RENAME ... COPY which tries to rename parent # table must acquire X lock on child table. connection con1; BEGIN; SELECT * FROM child; fk a connection default; ALTER TABLE parent RENAME TO parent1, ADD COLUMN a INT, ALGORITHM=COPY;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES parent1 TO parent; # 8.14) ALTER TABLE ... RENAME ... COPY which acquires lock on child # table and fails due to lock timeout. connection con1; BEGIN; SELECT * FROM child; fk a connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME TO parent1, ADD COLUMN b INT, ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; # 8.15) ALTER TABLE ... RENAME ... COPY which adds parent table for # orphan child must acquire X lock on this child table. connection default; DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; ALTER TABLE parent RENAME TO parent1, ADD COLUMN c INT, ALGORITHM=COPY;; connection con1; # Wait until ALTER TABLE is blocked by con1 and then resume it. COMMIT; connection default; # Reap ALTER TABLE RENAME TABLES parent1 TO parent; # 8.16) ALTER TABLE ... RENAME ... COPY which acquires lock on # orphan child table and fails due to timeout. DROP TABLE child; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent1(pk)); SET FOREIGN_KEY_CHECKS=1; connection con1; BEGIN; SELECT * FROM child; fk connection default; SET @@lock_wait_timeout= 1; ALTER TABLE parent RENAME TO parent1, ADD COLUMN d INT, ALGORITHM=COPY; ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET @@lock_wait_timeout= @old_lock_wait_timeout; connection con1; COMMIT; connection default; DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE CASCADE); # 8.17) ALTER TABLE ... RENAME ... COPY on the child table should # invalidate entries in TC/TDC and DD caches for the parent table. SELECT * FROM parent; pk a c connection con1; ALTER TABLE child RENAME TO child1, ADD COLUMN a INT, ALGORITHM=COPY; connection default; LOCK TABLE parent WRITE; connection con1; # The above LOCK TABLE should have noticed new table definition # and acquire SNRW lock on new child table name. SELECT * FROM child1;; connection default; # Wait until SELECT is blocked by default connection and then resume it. UNLOCK TABLES; connection con1; # Reap SELECT fk a connection default; DROP TABLES child1, parent; connection con1; disconnect con1; connection con2; disconnect con2; connection default; # # Validation of FK and referred column names. # # Too long constraint name. CREATE TABLE t (pk INTEGER PRIMARY KEY, fk_i INTEGER, CONSTRAINT xxxxxxxxx1xxxxxxxxx2xxxxxxxxx3xxxxxxxxx4xxxxxxxxx5xxxxxxxxx6xxxxx FOREIGN KEY (fk_i) REFERENCES x(x)); ERROR 42000: Identifier name 'xxxxxxxxx1xxxxxxxxx2xxxxxxxxx3xxxxxxxxx4xxxxxxxxx5xxxxxxxxx6xxxxx' is too long # Too long column name. CREATE TABLE t (pk INTEGER PRIMARY KEY, fk_i INTEGER, FOREIGN KEY (fk_i) REFERENCES x(xxxxxxxxx1xxxxxxxxx2xxxxxxxxx3xxxxxxxxx4xxxxxxxxx5xxxxxxxxx6xxxxx)); ERROR 42000: Incorrect column name 'xxxxxxxxx1xxxxxxxxx2xxxxxxxxx3xxxxxxxxx4xxxxxxxxx5xxxxxxxxx6xxxxx' # Column name having trailing space. CREATE TABLE t (pk INTEGER PRIMARY KEY, fk_i INTEGER, FOREIGN KEY (fk_i) REFERENCES x(`x `)); ERROR 42000: Incorrect column name 'x ' # # Test DROP of table with FKs under LOCK TABLES. # CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER, fk_i INTEGER, UNIQUE KEY parent_i_key(i), FOREIGN KEY (fk_i) REFERENCES parent(i)); CREATE TABLE child(pk INTEGER PRIMARY KEY, fk_i INTEGER, FOREIGN KEY (fk_i) REFERENCES parent(i)); SET @@session.foreign_key_checks= 1; # Drop only parent with FKC == 0. LOCK TABLE parent WRITE; DROP TABLES parent; ERROR HY000: Cannot drop table 'parent' referenced by a foreign key constraint 'child_ibfk_1' on table 'child'. UNLOCK TABLE; SET @@session.foreign_key_checks= 0; # Drop only parent. LOCK TABLE parent WRITE; DROP TABLES parent; UNLOCK TABLE; SET @@session.foreign_key_checks= 1; CREATE TABLE parent(pk INTEGER PRIMARY KEY, i INTEGER, UNIQUE KEY parent_i_key(i)); # Drop both child and parent. LOCK TABLES child WRITE, parent WRITE; DROP TABLES child, parent; UNLOCK TABLES; SET @@session.foreign_key_checks= DEFAULT; # # Test ALTER TABLE ... ADD FOREIGN KEY under LOCK TABLES. # CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT); LOCK TABLES child WRITE; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Table 'parent' was not locked with LOCK TABLES UNLOCK TABLES; # With parent table locked for read it should be possible to add FK. LOCK TABLES child WRITE, parent READ; ALTER TABLE child ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk); UNLOCK TABLES; # # Test ALTER TABLE ... RENAME with FKs under LOCK TABLES. # # Bug 26647340 "LIFT LIMITATION ON ALTER TABLE RENAME + TABLES WITH # FOREIGN KEYS + LOCK TABLES". # # Renaming of tables participating in FKs is allowed. LOCK TABLES child WRITE; ALTER TABLE child RENAME TO child1; UNLOCK TABLES; LOCK TABLES parent WRITE; ALTER TABLE parent RENAME TO parent1; UNLOCK TABLES; # Check that it doesn't break FK invariants for LOCK TABLES. LOCK TABLES child1 WRITE, parent1 WRITE; ALTER TABLE child1 RENAME TO child; INSERT INTO child VALUES (NULL); DELETE FROM parent1; UNLOCK TABLES; LOCK TABLES child WRITE, parent1 WRITE; ALTER TABLE parent1 RENAME TO parent; INSERT INTO child VALUES (NULL); UNLOCK TABLES; # It is also allowed to add foreign key along with rename. ALTER TABLE child DROP FOREIGN KEY fk; LOCK TABLES child WRITE, parent WRITE; ALTER TABLE child RENAME TO child1, ADD CONSTRAINT fk FOREIGN KEY (fk) REFERENCES parent(pk); # And FK invariants for LOCK TABLES are preserved too. INSERT INTO child1 VALUES (NULL); DELETE FROM parent; UNLOCK TABLES; DROP TABLE child1; # We also allow renames which add parent for previously orphan FKs. # Provided that we have write lock on these children. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY(fk) REFERENCES parent1(pk) ON DELETE CASCADE); SET FOREIGN_KEY_CHECKS=1; LOCK TABLE parent WRITE; ALTER TABLE parent RENAME TO parent1; ERROR HY000: Table 'child' was locked with a READ lock and can't be updated UNLOCK TABLES; LOCK TABLE parent WRITE, child READ; ALTER TABLE parent RENAME TO parent1; ERROR HY000: Table 'child' was locked with a READ lock and can't be updated UNLOCK TABLES; LOCK TABLE parent WRITE, child WRITE; ALTER TABLE parent RENAME TO parent1; # Invariants should be fine INSERT INTO child VALUES (NULL); DELETE FROM parent1; UNLOCK TABLES; DROP TABLES child, parent1; # # Bug #25722221 "RENAME COLUMN DID NOT UPDATE FOREIGN_KEY_COLUMN_USAGE # FOR FK CONSTRAINT". # Bug #26659110 "LIFT LIMITATION ON RENAMING PARENT COLUMNS WHICH ARE # REFERENCED BY FOREIGN KEYS". # CREATE TABLE t1 (pk INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES t1 (pk)); SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 pk NULL t1_ibfk_1 t1 fk pk ALTER TABLE t1 CHANGE pk id INT; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 id NULL t1_ibfk_1 t1 fk id # Renaming of parent columns using COPY algorithm is not supported. ALTER TABLE t1 CHANGE id pk INT, ALGORITHM=COPY; ERROR 0A000: ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE. SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 id NULL t1_ibfk_1 t1 fk id ALTER TABLE t1 CHANGE id pk INT, ALGORITHM=INPLACE; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 pk NULL t1_ibfk_1 t1 fk pk ALTER TABLE t1 RENAME COLUMN pk TO id; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 id NULL t1_ibfk_1 t1 fk id # Renaming of parent columns using COPY algorithm is not supported. ALTER TABLE t1 RENAME COLUMN id TO pk, ALGORITHM=COPY; ERROR 0A000: ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE. SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 id NULL t1_ibfk_1 t1 fk id ALTER TABLE t1 RENAME COLUMN id TO pk, ALGORITHM=INPLACE; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 pk NULL t1_ibfk_1 t1 fk pk DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY); CREATE TABLE t2 (fk INT, FOREIGN KEY (fk) REFERENCES t1 (pk)); SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk pk ALTER TABLE t1 CHANGE pk id INT; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk id # Renaming of parent columns using COPY algorithm is not supported. ALTER TABLE t1 CHANGE id pk INT, ALGORITHM=COPY; ERROR 0A000: ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE. SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk id ALTER TABLE t1 CHANGE id pk INT, ALGORITHM=INPLACE; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk pk ALTER TABLE t1 RENAME COLUMN pk TO id; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk id # Renaming of parent columns using COPY algorithm is not supported. ALTER TABLE t1 RENAME COLUMN id TO pk, ALGORITHM=COPY; ERROR 0A000: ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE. SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk id ALTER TABLE t1 RENAME COLUMN id TO pk, ALGORITHM=INPLACE; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk pk DROP TABLES t2, t1; # Coverage for cases with multiple foreign keys. CREATE TABLE t1 (pk INT PRIMARY KEY, u1 INT, u2 INT, fk1 INT, fk2 INT, UNIQUE (u1), UNIQUE (u2), FOREIGN KEY (fk1) REFERENCES t1 (u1), FOREIGN KEY (fk2) REFERENCES t1 (u2)); SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 pk NULL u1 t1 u1 NULL u2 t1 u2 NULL t1_ibfk_1 t1 fk1 u1 t1_ibfk_2 t1 fk2 u2 ALTER TABLE t1 RENAME COLUMN u1 TO u3; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 pk NULL u1 t1 u3 NULL u2 t1 u2 NULL t1_ibfk_1 t1 fk1 u3 t1_ibfk_2 t1 fk2 u2 ALTER TABLE t1 RENAME COLUMN u3 TO u4, RENAME COLUMN u2 TO u5; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t1'; constraint_name table_name column_name referenced_column_name PRIMARY t1 pk NULL u1 t1 u4 NULL u2 t1 u5 NULL t1_ibfk_1 t1 fk1 u4 t1_ibfk_2 t1 fk2 u5 DROP TABLE t1; CREATE TABLE t1 (pk INT PRIMARY KEY, u1 INT, u2 INT, UNIQUE (u1), UNIQUE (u2)); CREATE TABLE t2 (fk1 INT, fk2 INT, FOREIGN KEY (fk1) REFERENCES t1 (u1), FOREIGN KEY (fk2) REFERENCES t1 (u2)); SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk1 u1 t2_ibfk_2 t2 fk2 u2 ALTER TABLE t1 RENAME COLUMN u1 TO u3; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk1 u3 t2_ibfk_2 t2 fk2 u2 ALTER TABLE t1 RENAME COLUMN u3 TO u4, RENAME COLUMN u2 TO u5; SELECT constraint_name, table_name, column_name, referenced_column_name FROM information_schema.key_column_usage WHERE table_schema='test' AND table_name='t2'; constraint_name table_name column_name referenced_column_name t2_ibfk_1 t2 fk1 u4 t2_ibfk_2 t2 fk2 u5 DROP TABLES t2, t1; # # WL#6049, bug#26654674 "TABLE_CACHE_MANAGER::FREE_TABLE(THD*, # ENUM_TDC_REMOVE_TABLE_TYPE, TABLE_SHARE*)". # CREATE TABLE t1 (u INT NOT NULL, UNIQUE u(u)); # First, check that we correctly handle open HANDLERs during # parent invalidation. HANDLER t1 OPEN; CREATE TABLE t2 (fk INT, FOREIGN KEY (fk) REFERENCES t1 (u)); HANDLER t1 CLOSE; HANDLER t1 OPEN AS a; HANDLER t1 OPEN AS b; CREATE TABLE t3 (fk INT, FOREIGN KEY (fk) REFERENCES t1 (u)); HANDLER a CLOSE; HANDLER b CLOSE; # Then, check that we correctly handle HANDLERs on child table # during parent definiton change. HANDLER t2 OPEN; HANDLER t3 OPEN AS a; HANDLER t3 OPEN AS b; ALTER TABLE t1 RENAME KEY u TO u1; HANDLER t2 CLOSE; HANDLER a CLOSE; HANDLER b CLOSE; # Now, let us check what happens when parent is renamed. HANDLER t2 OPEN; HANDLER t3 OPEN AS a; HANDLER t3 OPEN AS b; ALTER TABLE t1 RENAME TO t4; HANDLER t2 CLOSE; HANDLER a CLOSE; HANDLER b CLOSE; # Finally, check what happens when parent table is deleted. # Do clean-up as side-effect. HANDLER t2 OPEN; HANDLER t3 OPEN AS a; HANDLER t3 OPEN AS b; SET FOREIGN_KEY_CHECKS=0; DROP TABLE t4; DROP TABLES t2, t3; SET FOREIGN_KEY_CHECKS=1; # # Additional test coverage for foreign keys and prepared statement # validation. # CREATE TABLE t1 (i INT PRIMARY KEY); CREATE TABLE t2 (j INT, FOREIGN KEY (j) REFERENCES t1 (i) ON DELETE CASCADE); CREATE TABLE t3 (k INT); CREATE TRIGGER bi_t3 BEFORE INSERT ON t3 FOR EACH ROW BEGIN IF @a = 1234567890 THEN DELETE FROM t1; END IF; END| PREPARE stmt FROM 'INSERT INTO t3 VALUES (1)'; EXECUTE stmt; DROP TABLES t2, t1; # Statement should succeed even though we won't be able check # prelocked set element for child table. EXECUTE stmt; CREATE TABLE t1 (i INT PRIMARY KEY); CREATE TABLE t2 (j INT, FOREIGN KEY (j) REFERENCES t1 (i) ON DELETE CASCADE); EXECUTE stmt; DROP TABLES t2, t1; CREATE VIEW t2 AS SELECT 1 AS j; # Again statement should succeed, even though we have view instead # of child table. EXECUTE stmt; DEALLOCATE PREPARE stmt; DROP TABLE t3; DROP VIEW t2; # # Test for bug #27041477 "ASSERTION `HAS_PRELOCKING_LIST || # THD->MDL_CONTEXT.OWNS_EQUAL_OR_STRONGER_LOCK". # CREATE TABLE t0 (i INT); CREATE TRIGGER t0_bi BEFORE INSERT ON t0 FOR EACH ROW DELETE FROM t1; CREATE TABLE t1 (pk INT PRIMARY KEY); CREATE TABLE t2 (fk INT, FOREIGN KEY (fk) REFERENCES t1 (pk) ON UPDATE SET NULL); LOCK TABLE t1 READ; DELETE FROM t1; ERROR HY000: Table 't2' was not locked with LOCK TABLES UNLOCK TABLES; LOCK TABLES t0 WRITE; UPDATE t1 SET pk = 10; ERROR HY000: Table 't2' was locked with a READ lock and can't be updated UNLOCK TABLES; DROP TABLES t2, t1, t0; # # Additional coverage for bug #25915132 "INPLACE ALTER TABLE WITH # FOREIGN KEYS CAUSES TABLE DEFINITION MISMATCH". # # # Handling of foreign key names during various RENAME variants. # We check that table definition is updated correctly and that # asserts about MDL on foreign key names do not fail. # CREATE TABLE t1 (pk INT PRIMARY KEY); CREATE TABLE t2 (fk1 INT, fk2 INT, fk3 INT, CONSTRAINT a FOREIGN KEY (fk1) REFERENCES t1 (pk), CONSTRAINT t2_ibfk_1 FOREIGN KEY (fk2) REFERENCES t1 (pk)); ALTER TABLE t2 ADD FOREIGN KEY (fk3) REFERENCES t1 (pk); CREATE SCHEMA mysqltest; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t2 t1 def test t2_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t2 t1 def test t2_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t2 t1 # Simple RENAME TABLE RENAME TABLE t2 TO t3; SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t3 t1 def test t3_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t3 t1 def test t3_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t3 t1 # Two cross database RENAME TABLE variants RENAME TABLE t3 TO mysqltest.t3; SHOW CREATE TABLE mysqltest.t3; Table Create Table t3 CREATE TABLE `t3` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `test`.`t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='mysqltest'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def mysqltest a def test PRIMARY NONE NO ACTION NO ACTION t3 t1 def mysqltest t3_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t3 t1 def mysqltest t3_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t3 t1 RENAME TABLE mysqltest.t3 TO t4; SHOW CREATE TABLE t4; Table Create Table t4 CREATE TABLE `t4` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t4_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t4 t1 def test t4_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t4 t1 def test t4_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t4 t1 # Simple ALTER TABLE RENAME variants. ALTER TABLE t4 RENAME TO t5; SHOW CREATE TABLE t5; Table Create Table t5 CREATE TABLE `t5` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t5_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t5_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t5 t1 def test t5_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t5 t1 def test t5_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t5 t1 ALTER TABLE t5 RENAME TO mysqltest.t5; SHOW CREATE TABLE mysqltest.t5; Table Create Table t5 CREATE TABLE `t5` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t5_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t5_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `test`.`t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='mysqltest'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def mysqltest a def test PRIMARY NONE NO ACTION NO ACTION t5 t1 def mysqltest t5_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t5 t1 def mysqltest t5_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t5 t1 ALTER TABLE mysqltest.t5 RENAME TO t6; SHOW CREATE TABLE t6; Table Create Table t6 CREATE TABLE `t6` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t6_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t6_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t6 t1 def test t6_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t6 t1 def test t6_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t6 t1 # ALTER TABLE INPLACE with RENAME clause. ALTER TABLE t6 ADD COLUMN i INT, RENAME TO t7, ALGORITHM=INPLACE; SHOW CREATE TABLE t7; Table Create Table t7 CREATE TABLE `t7` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t7_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t7_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t7 t1 def test t7_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t7 t1 def test t7_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t7 t1 ALTER TABLE t7 ADD COLUMN j INT, RENAME TO mysqltest.t7, ALGORITHM=INPLACE; SHOW CREATE TABLE mysqltest.t7; Table Create Table t7 CREATE TABLE `t7` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t7_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t7_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `test`.`t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='mysqltest'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def mysqltest a def test PRIMARY NONE NO ACTION NO ACTION t7 t1 def mysqltest t7_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t7 t1 def mysqltest t7_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t7 t1 ALTER TABLE mysqltest.t7 ADD COLUMN k INT, RENAME TO t8, ALGORITHM=INPLACE; SHOW CREATE TABLE t8; Table Create Table t8 CREATE TABLE `t8` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t8_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t8_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t8 t1 def test t8_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t8 t1 def test t8_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t8 t1 # ALTER TABLE COPY with RENAME clause. ALTER TABLE t8 ADD COLUMN l INT, RENAME TO t9, ALGORITHM=COPY; SHOW CREATE TABLE t9; Table Create Table t9 CREATE TABLE `t9` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t9_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t9_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t9 t1 def test t9_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t9 t1 def test t9_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t9 t1 ALTER TABLE t9 ADD COLUMN m INT, RENAME TO mysqltest.t9, ALGORITHM=COPY; SHOW CREATE TABLE mysqltest.t9; Table Create Table t9 CREATE TABLE `t9` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t9_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t9_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `test`.`t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='mysqltest'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def mysqltest a def test PRIMARY NONE NO ACTION NO ACTION t9 t1 def mysqltest t9_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t9 t1 def mysqltest t9_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t9 t1 ALTER TABLE mysqltest.t9 ADD COLUMN n INT, RENAME TO t10, ALGORITHM=COPY; SHOW CREATE TABLE t10; Table Create Table t10 CREATE TABLE `t10` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t10_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t10_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t10 t1 def test t10_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t10 t1 def test t10_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t10 t1 # ALTER TABLE INPLACE + ADD FOREIGN KEY with RENAME clause. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE t10 ADD FOREIGN KEY (i) REFERENCES t1 (pk), ADD CONSTRAINT t10_ibfk_4 FOREIGN KEY (j) REFERENCES t1 (pk), RENAME TO t11, ALGORITHM=INPLACE; SHOW CREATE TABLE t11; Table Create Table t11 CREATE TABLE `t11` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), KEY `i` (`i`), KEY `t10_ibfk_4` (`j`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t11_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t11_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`), CONSTRAINT `t11_ibfk_3` FOREIGN KEY (`i`) REFERENCES `t1` (`pk`), CONSTRAINT `t11_ibfk_4` FOREIGN KEY (`j`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def test t11_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def test t11_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def test t11_ibfk_3 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def test t11_ibfk_4 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 ALTER TABLE t11 ADD FOREIGN KEY (k) REFERENCES test.t1 (pk), ADD CONSTRAINT t11_ibfk_6 FOREIGN KEY (l) REFERENCES test.t1 (pk), RENAME TO mysqltest.t11, ALGORITHM=INPLACE; SHOW CREATE TABLE mysqltest.t11; Table Create Table t11 CREATE TABLE `t11` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), KEY `i` (`i`), KEY `t10_ibfk_4` (`j`), KEY `k` (`k`), KEY `t11_ibfk_6` (`l`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t11_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t11_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t11_ibfk_3` FOREIGN KEY (`i`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t11_ibfk_4` FOREIGN KEY (`j`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t11_ibfk_5` FOREIGN KEY (`k`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t11_ibfk_6` FOREIGN KEY (`l`) REFERENCES `test`.`t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='mysqltest'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def mysqltest a def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def mysqltest t11_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def mysqltest t11_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def mysqltest t11_ibfk_3 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def mysqltest t11_ibfk_4 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def mysqltest t11_ibfk_5 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 def mysqltest t11_ibfk_6 def test PRIMARY NONE NO ACTION NO ACTION t11 t1 ALTER TABLE mysqltest.t11 ADD FOREIGN KEY (m) REFERENCES test.t1 (pk), ADD CONSTRAINT t12_ibfk_8 FOREIGN KEY (n) REFERENCES test.t1 (pk), RENAME TO t12, ALGORITHM=INPLACE; SHOW CREATE TABLE t12; Table Create Table t12 CREATE TABLE `t12` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), KEY `i` (`i`), KEY `t10_ibfk_4` (`j`), KEY `k` (`k`), KEY `t11_ibfk_6` (`l`), KEY `m` (`m`), KEY `t12_ibfk_8` (`n`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_3` FOREIGN KEY (`i`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_4` FOREIGN KEY (`j`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_5` FOREIGN KEY (`k`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_6` FOREIGN KEY (`l`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_7` FOREIGN KEY (`m`) REFERENCES `t1` (`pk`), CONSTRAINT `t12_ibfk_8` FOREIGN KEY (`n`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_3 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_4 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_5 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_6 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_7 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 def test t12_ibfk_8 def test PRIMARY NONE NO ACTION NO ACTION t12 t1 SET FOREIGN_KEY_CHECKS=1; # ALTER TABLE COPY + ADD FOREIGN KEY with RENAME clause. ALTER TABLE t12 ADD COLUMN o INT, ADD COLUMN p INT, ADD FOREIGN KEY (o) REFERENCES t1 (pk), ADD CONSTRAINT t12_ibfk_10 FOREIGN KEY (p) REFERENCES t1 (pk), RENAME TO t13, ALGORITHM=COPY; SHOW CREATE TABLE t13; Table Create Table t13 CREATE TABLE `t13` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, `o` int(11) DEFAULT NULL, `p` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), KEY `i` (`i`), KEY `t10_ibfk_4` (`j`), KEY `k` (`k`), KEY `t11_ibfk_6` (`l`), KEY `m` (`m`), KEY `t12_ibfk_8` (`n`), KEY `o` (`o`), KEY `t12_ibfk_10` (`p`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_10` FOREIGN KEY (`p`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_3` FOREIGN KEY (`i`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_4` FOREIGN KEY (`j`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_5` FOREIGN KEY (`k`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_6` FOREIGN KEY (`l`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_7` FOREIGN KEY (`m`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_8` FOREIGN KEY (`n`) REFERENCES `t1` (`pk`), CONSTRAINT `t13_ibfk_9` FOREIGN KEY (`o`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_10 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_3 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_4 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_5 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_6 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_7 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_8 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def test t13_ibfk_9 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 ALTER TABLE t13 ADD COLUMN q INT, ADD COLUMN r INT, ADD FOREIGN KEY (q) REFERENCES test.t1 (pk), ADD CONSTRAINT t13_ibfk_12 FOREIGN KEY (r) REFERENCES test.t1 (pk), RENAME TO mysqltest.t13, ALGORITHM=COPY; SHOW CREATE TABLE mysqltest.t13; Table Create Table t13 CREATE TABLE `t13` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, `o` int(11) DEFAULT NULL, `p` int(11) DEFAULT NULL, `q` int(11) DEFAULT NULL, `r` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), KEY `i` (`i`), KEY `t10_ibfk_4` (`j`), KEY `k` (`k`), KEY `t11_ibfk_6` (`l`), KEY `m` (`m`), KEY `t12_ibfk_8` (`n`), KEY `o` (`o`), KEY `t12_ibfk_10` (`p`), KEY `q` (`q`), KEY `t13_ibfk_12` (`r`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_10` FOREIGN KEY (`p`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_11` FOREIGN KEY (`q`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_12` FOREIGN KEY (`r`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_3` FOREIGN KEY (`i`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_4` FOREIGN KEY (`j`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_5` FOREIGN KEY (`k`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_6` FOREIGN KEY (`l`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_7` FOREIGN KEY (`m`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_8` FOREIGN KEY (`n`) REFERENCES `test`.`t1` (`pk`), CONSTRAINT `t13_ibfk_9` FOREIGN KEY (`o`) REFERENCES `test`.`t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='mysqltest'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def mysqltest a def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_10 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_11 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_12 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_3 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_4 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_5 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_6 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_7 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_8 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 def mysqltest t13_ibfk_9 def test PRIMARY NONE NO ACTION NO ACTION t13 t1 ALTER TABLE mysqltest.t13 ADD COLUMN s INT, ADD COLUMN t INT, ADD FOREIGN KEY (s) REFERENCES test.t1 (pk), ADD CONSTRAINT t13_ibfk_14 FOREIGN KEY (t) REFERENCES test.t1 (pk), RENAME TO t14, ALGORITHM=COPY; SHOW CREATE TABLE t14; Table Create Table t14 CREATE TABLE `t14` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `i` int(11) DEFAULT NULL, `j` int(11) DEFAULT NULL, `k` int(11) DEFAULT NULL, `l` int(11) DEFAULT NULL, `m` int(11) DEFAULT NULL, `n` int(11) DEFAULT NULL, `o` int(11) DEFAULT NULL, `p` int(11) DEFAULT NULL, `q` int(11) DEFAULT NULL, `r` int(11) DEFAULT NULL, `s` int(11) DEFAULT NULL, `t` int(11) DEFAULT NULL, KEY `a` (`fk1`), KEY `t2_ibfk_1` (`fk2`), KEY `fk3` (`fk3`), KEY `i` (`i`), KEY `t10_ibfk_4` (`j`), KEY `k` (`k`), KEY `t11_ibfk_6` (`l`), KEY `m` (`m`), KEY `t12_ibfk_8` (`n`), KEY `o` (`o`), KEY `t12_ibfk_10` (`p`), KEY `q` (`q`), KEY `t13_ibfk_12` (`r`), KEY `s` (`s`), KEY `t13_ibfk_14` (`t`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_1` FOREIGN KEY (`fk2`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_10` FOREIGN KEY (`p`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_11` FOREIGN KEY (`q`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_12` FOREIGN KEY (`r`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_13` FOREIGN KEY (`s`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_14` FOREIGN KEY (`t`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_3` FOREIGN KEY (`i`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_4` FOREIGN KEY (`j`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_5` FOREIGN KEY (`k`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_6` FOREIGN KEY (`l`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_7` FOREIGN KEY (`m`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_8` FOREIGN KEY (`n`) REFERENCES `t1` (`pk`), CONSTRAINT `t14_ibfk_9` FOREIGN KEY (`o`) REFERENCES `t1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM information_schema.referential_constraints WHERE constraint_schema='test'; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test a def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_1 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_10 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_11 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_12 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_13 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_14 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_2 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_3 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_4 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_5 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_6 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_7 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_8 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 def test t14_ibfk_9 def test PRIMARY NONE NO ACTION NO ACTION t14 t1 DROP TABLE t14; # # Detection of duplicate foreign key names by various forms of ALTER # TABLE. # CREATE TABLE t2 (fk INT, CONSTRAINT c FOREIGN KEY (fk) REFERENCES t1 (pk)); CREATE TABLE t3 (pk INT PRIMARY KEY, fk INT, u INT); INSERT INTO t3 VALUES (1, 1, 1), (2, 1, 1); # # ALTER TABLE INPLACE # SET FOREIGN_KEY_CHECKS=0; # Duplicate FK name should be detected before we start addition # of unique key and report its violation. ALTER TABLE t3 ADD CONSTRAINT c FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 'c' # Even for generated names. CREATE TABLE t4 (fk INT, CONSTRAINT t3_ibfk_1 FOREIGN KEY (fk) REFERENCES t1 (pk)); ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 't3_ibfk_1' # There should not be conflicting foreign keys before main phase # of ALTER INPLACE even if at the end RENAME clause will remove # conflict. ALTER TABLE t3 ADD CONSTRAINT c FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO mysqltest.t3, ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 'c' ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO t5, ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 't3_ibfk_1' # Now let us check that we detect potential conflicts resulting # from application of RENAME clause, before ALTER INPLACE main # phase as well. CREATE TABLE mysqltest.t5 (fk INT, CONSTRAINT d FOREIGN KEY (fk) REFERENCES test.t1 (pk)); CREATE TABLE t6 (fk INT, CONSTRAINT t8_ibfk_1 FOREIGN KEY (fk) REFERENCES test.t1 (pk)); CREATE TABLE mysqltest.t6 (fk INT, CONSTRAINT t8_ibfk_1 FOREIGN KEY (fk) REFERENCES test.t1 (pk)); DROP TABLE t4; ALTER TABLE t3 ADD CONSTRAINT d FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO mysqltest.t3, ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 'd' ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO t8, ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 't8_ibfk_1' ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO mysqltest.t8, ALGORITHM=INPLACE; ERROR HY000: Duplicate foreign key constraint name 't8_ibfk_1' SET FOREIGN_KEY_CHECKS=1; # # ALTER TABLE COPY # # Duplicate FK name should be detected before we start copying # of rows and report unique/FK constraint violation. ALTER TABLE t3 ADD CONSTRAINT c FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), ALGORITHM=COPY; ERROR HY000: Duplicate foreign key constraint name 'c' # Even for generated names. CREATE TABLE t4 (fk INT, CONSTRAINT t3_ibfk_1 FOREIGN KEY (fk) REFERENCES t1 (pk)); ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), ALGORITHM=COPY; ERROR HY000: Duplicate foreign key constraint name 't3_ibfk_1' # Unlike in INPLACE case, COPY algorithm creates FKs right # away in schema targeted by RENAME clause. So it doesn't # matter if constraint with the same name exists in the # table's original schema. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE t3 ADD CONSTRAINT c FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO mysqltest.t3, ALGORITHM=COPY; ERROR 23000: Duplicate entry '1' for key 'u' SET FOREIGN_KEY_CHECKS=1; # Updating of generated names still happens at the end of ALTER, # so there should not be conflicting foreign keys for generated # names for both old and new table name. ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES t1 (pk), ADD UNIQUE KEY (u), RENAME TO t5, ALGORITHM=COPY; ERROR HY000: Duplicate foreign key constraint name 't3_ibfk_1' # Check that we detect potential conflicts resulting from # application of RENAME clause early. DROP TABLE t4; ALTER TABLE t3 ADD CONSTRAINT d FOREIGN KEY (fk) REFERENCES test.t1 (pk), ADD UNIQUE KEY (u), RENAME TO mysqltest.t3, ALGORITHM=COPY; ERROR HY000: Duplicate foreign key constraint name 'd' ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES test.t1 (pk), ADD UNIQUE KEY (u), RENAME TO t8, ALGORITHM=COPY; ERROR HY000: Duplicate foreign key constraint name 't8_ibfk_1' ALTER TABLE t3 ADD FOREIGN KEY (fk) REFERENCES test.t1 (pk), ADD UNIQUE KEY (u), RENAME TO mysqltest.t8, ALGORITHM=COPY; ERROR HY000: Duplicate foreign key constraint name 't8_ibfk_1' DROP SCHEMA mysqltest; DROP TABLES t6, t3, t2, t1; # # Initial version of the fix triggered asserts in the below statements. # CREATE TABLE t1 (pk INT PRIMARY KEY); CREATE TABLE T2 (fk INT); ALTER TABLE T2 ADD FOREIGN KEY (fk) REFERENCES t1 (pk); RENAME TABLE T2 TO T3; DROP TABLES T3, t1; # # Bug #27821060 "NEWDD FK: DROP TABLES/DATABASE SHOULD CHECK FOR FKS". # # # 1) Attempt to DROP TABLE which serves as parent in FK without dropping # child should fail with nice error message. CREATE TABLE t1 (pk INT PRIMARY KEY); CREATE TABLE t2 (fk INT, FOREIGN KEY (fk) REFERENCES t1 (pk)); DROP TABLE t1; ERROR HY000: Cannot drop table 't1' referenced by a foreign key constraint 't2_ibfk_1' on table 't2'. # # 2) However, same should be allowed in FOREIGN_KEY_CHECKS=0 mode. SET FOREIGN_KEY_CHECKS=0; DROP TABLE t1; SET FOREIGN_KEY_CHECKS=1; # # 3) Dropping of parent table along with child table should be allowed. # Even if parent precedes child in table list. CREATE TABLE t1 (pk INT PRIMARY KEY); DROP TABLES t1, t2; # # 4) Even if FKs form circular dependencies. CREATE TABLE t1 (pk INT PRIMARY KEY, fk INT); CREATE TABLE t2 (pk INT PRIMARY KEY, fk INT, FOREIGN KEY(fk) REFERENCES t1 (pk)); ALTER TABLE t1 ADD FOREIGN KEY (fk) REFERENCES t2 (pk); DROP TABLES t1, t2; # # 5) Attempt to DROP SCHEMA which will remove parent without # removing child should fail with nice error message. CREATE SCHEMA mysqltest; CREATE TABLE mysqltest.t1 (pk INT PRIMARY KEY); CREATE TABLE t2 (fk INT, FOREIGN KEY(fk) REFERENCES mysqltest.t1 (pk)); DROP SCHEMA mysqltest; ERROR HY000: Cannot drop table 't1' referenced by a foreign key constraint 't2_ibfk_1' on table 't2'. # # 6) But the same should be allowed in FOREIGN_KEY_CHECKS=0 mode. SET FOREIGN_KEY_CHECKS=0; DROP SCHEMA mysqltest; SET FOREIGN_KEY_CHECKS=1; DROP TABLE t2; # # 7) Also dropping schema which drops both parent and child # should be OK. CREATE SCHEMA mysqltest; USE mysqltest; CREATE TABLE t1 (pk INT PRIMARY KEY, fk INT); CREATE TABLE t2 (pk INT PRIMARY KEY, fk INT, FOREIGN KEY(fk) REFERENCES t1 (pk)); ALTER TABLE t1 ADD FOREIGN KEY (fk) REFERENCES t2 (pk); USE test; DROP SCHEMA mysqltest; # # Bug#27506922 "DROPPING OF PARENT KEY FOR FOREIGN KEY IS ALLOWED". # # # 1) CREATE TABLE with FK and no parent key. # CREATE TABLE parent(pk INT PRIMARY KEY, a INT); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE self (pk INT PRIMARY KEY, a INT, fk INT, FOREIGN KEY (fk) REFERENCES self(a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE self (pk INT PRIMARY KEY, a INT, fk INT, FOREIGN KEY (fk) REFERENCES self(a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' # Missing parent table case. SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES no_such_parent(pk)); ERROR HY000: Failed to open the referenced table 'no_such_parent' # We allow creation of orphan FKs in FOREIGN_KEY_CHECKS = 0 mode. SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES no_such_parent(pk)); SET FOREIGN_KEY_CHECKS = 1; DROP TABLE child; # # 2) ALTER TABLE which adds FK without parent key. # CREATE TABLE child (fk INT, fk2 INT); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(a), ALGORITHM=COPY; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(a), ALGORITHM=INPLACE; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(a), ALGORITHM=COPY; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(a), ALGORITHM=INPLACE; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE self (pk INT PRIMARY KEY, a INT, fk INT); ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(a), ALGORITHM=COPY; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(a), ALGORITHM=INPLACE; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(a), ALGORITHM=COPY; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(a), ALGORITHM=INPLACE; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' # Missing parent table case. SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES no_such_parent(pk), ALGORITHM=COPY; ERROR HY000: Failed to open the referenced table 'no_such_parent' ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES no_such_parent(pk), ALGORITHM=INPLACE; ERROR HY000: Failed to open the referenced table 'no_such_parent' # We allow creation of orphan FKs in FOREIGN_KEY_CHECKS = 0 mode. SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES no_such_parent(pk), ALGORITHM=COPY; ALTER TABLE child ADD FOREIGN KEY (fk2) REFERENCES no_such_parent(pk), ALGORITHM=INPLACE; SET FOREIGN_KEY_CHECKS = 1; DROP TABLE child, self, parent; # # 3) ALTER TABLE which drops parent key. # CREATE TABLE parent (pk INT PRIMARY KEY, u INT NOT NULL, UNIQUE(u)); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(u)); ALTER TABLE parent DROP KEY u, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint ALTER TABLE parent DROP KEY u, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE parent DROP KEY u, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint ALTER TABLE parent DROP KEY u, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE self (pk INT PRIMARY KEY, u INT NOT NULL, fk INT, UNIQUE(u), FOREIGN KEY (fk) REFERENCES self(u)); ALTER TABLE self DROP KEY u, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint ALTER TABLE self DROP KEY u, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE self DROP KEY u, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint ALTER TABLE self DROP KEY u, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'u': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 1; # Check case which requires additional handling during error-reporting. # Attempt to drop non-unique parent key. ALTER TABLE parent DROP KEY u, ADD KEY nu(u); ALTER TABLE parent DROP KEY nu, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint ALTER TABLE parent DROP KEY nu, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE parent DROP KEY nu, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint ALTER TABLE parent DROP KEY nu, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE self DROP KEY u, ADD KEY nu(u); ALTER TABLE self DROP KEY nu, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint ALTER TABLE self DROP KEY nu, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE self DROP KEY nu, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint ALTER TABLE self DROP KEY nu, ALGORITHM=INPLACE; ERROR HY000: Cannot drop index 'nu': needed in a foreign key constraint SET FOREIGN_KEY_CHECKS = 1; DROP TABLES self, child, parent; # # 4) CREATE, RENAME and ALTER TABLE RENAME which create new # parent for previously orphan child table. # SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(a)); SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE parent (pk INT PRIMARY KEY, a INT); ERROR HY000: Cannot add foreign key constraint SET FOREIGN_KEY_CHECKS = 0; CREATE TABLE parent (pk INT PRIMARY KEY, a INT); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; CREATE TABLE parent1 (pk INT PRIMARY KEY, a INT); RENAME TABLE parent1 TO parent; ERROR HY000: Error on rename of './test/parent1' to './test/parent' (errno: 150 - Foreign key constraint is incorrectly formed) SET FOREIGN_KEY_CHECKS = 0; RENAME TABLE parent1 TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE parent1 RENAME TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE parent1 RENAME TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE parent1 ADD COLUMN b INT, RENAME TO parent, ALGORITHM=INPLACE; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE parent1 RENAME TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE parent1 ADD COLUMN b INT, RENAME TO parent, ALGORITHM=COPY; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 0; ALTER TABLE parent1 RENAME TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS = 1; DROP TABLE parent1, child; # # 5) Special case. ALTER TABLE which replaces parent key with another # one due to new key creation. Old key is generated so it is # automagically replaced with a new explicit key or more universal # generated key. # CREATE TABLE grandparent (pk INT PRIMARY KEY); CREATE TABLE parent (pkfk INT, FOREIGN KEY (pkfk) REFERENCES grandparent(pk)); SHOW CREATE TABLE parent; Table Create Table parent CREATE TABLE `parent` ( `pkfk` int(11) DEFAULT NULL, KEY `pkfk` (`pkfk`), CONSTRAINT `parent_ibfk_1` FOREIGN KEY (`pkfk`) REFERENCES `grandparent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pkfk)); SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'child'; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME parent NULL ALTER TABLE parent ADD UNIQUE KEY u (pkfk); SHOW CREATE TABLE parent; Table Create Table parent CREATE TABLE `parent` ( `pkfk` int(11) DEFAULT NULL, UNIQUE KEY `u` (`pkfk`), CONSTRAINT `parent_ibfk_1` FOREIGN KEY (`pkfk`) REFERENCES `grandparent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'child'; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME parent u DROP TABLE child, parent; CREATE TABLE self (fk INT, pkfk INT, FOREIGN KEY (fk) REFERENCES self (pkfk), FOREIGN KEY (pkfk) REFERENCES grandparent(pk)); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `fk` int(11) DEFAULT NULL, `pkfk` int(11) DEFAULT NULL, KEY `fk` (`fk`), KEY `pkfk` (`pkfk`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `self` (`pkfk`), CONSTRAINT `self_ibfk_2` FOREIGN KEY (`pkfk`) REFERENCES `grandparent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'self' ORDER BY referenced_table_name; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME grandparent PRIMARY self NULL ALTER TABLE self ADD UNIQUE KEY u (pkfk); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `fk` int(11) DEFAULT NULL, `pkfk` int(11) DEFAULT NULL, UNIQUE KEY `u` (`pkfk`), KEY `fk` (`fk`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `self` (`pkfk`), CONSTRAINT `self_ibfk_2` FOREIGN KEY (`pkfk`) REFERENCES `grandparent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'self' ORDER BY referenced_table_name; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME grandparent PRIMARY self u DROP TABLE self, grandparent; CREATE TABLE grandparent1 (pk INT PRIMARY KEY); CREATE TABLE grandparent2 (pk1 INT , pk2 INT, PRIMARY KEY(pk1, pk2)); CREATE TABLE parent (pkfk1 INT, pkfk2 INT, FOREIGN KEY (pkfk1) REFERENCES grandparent1(pk)); SHOW CREATE TABLE parent; Table Create Table parent CREATE TABLE `parent` ( `pkfk1` int(11) DEFAULT NULL, `pkfk2` int(11) DEFAULT NULL, KEY `pkfk1` (`pkfk1`), CONSTRAINT `parent_ibfk_1` FOREIGN KEY (`pkfk1`) REFERENCES `grandparent1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pkfk1)); SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'child'; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME parent NULL ALTER TABLE parent ADD FOREIGN KEY (pkfk1, pkfk2) REFERENCES grandparent2(pk1, pk2); SHOW CREATE TABLE parent; Table Create Table parent CREATE TABLE `parent` ( `pkfk1` int(11) DEFAULT NULL, `pkfk2` int(11) DEFAULT NULL, KEY `pkfk1` (`pkfk1`,`pkfk2`), CONSTRAINT `parent_ibfk_1` FOREIGN KEY (`pkfk1`) REFERENCES `grandparent1` (`pk`), CONSTRAINT `parent_ibfk_2` FOREIGN KEY (`pkfk1`, `pkfk2`) REFERENCES `grandparent2` (`pk1`, `pk2`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'child'; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME parent NULL DROP TABLE child, parent; CREATE TABLE self (fk INT, pkfk1 INT, pkfk2 INT, FOREIGN KEY (fk) REFERENCES self (pkfk1), FOREIGN KEY (pkfk1) REFERENCES grandparent1(pk)); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `fk` int(11) DEFAULT NULL, `pkfk1` int(11) DEFAULT NULL, `pkfk2` int(11) DEFAULT NULL, KEY `fk` (`fk`), KEY `pkfk1` (`pkfk1`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `self` (`pkfk1`), CONSTRAINT `self_ibfk_2` FOREIGN KEY (`pkfk1`) REFERENCES `grandparent1` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'self' ORDER BY referenced_table_name; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME grandparent1 PRIMARY self NULL ALTER TABLE self ADD FOREIGN KEY (pkfk1, pkfk2) REFERENCES grandparent2(pk1, pk2); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `fk` int(11) DEFAULT NULL, `pkfk1` int(11) DEFAULT NULL, `pkfk2` int(11) DEFAULT NULL, KEY `fk` (`fk`), KEY `pkfk1` (`pkfk1`,`pkfk2`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `self` (`pkfk1`), CONSTRAINT `self_ibfk_2` FOREIGN KEY (`pkfk1`) REFERENCES `grandparent1` (`pk`), CONSTRAINT `self_ibfk_3` FOREIGN KEY (`pkfk1`, `pkfk2`) REFERENCES `grandparent2` (`pk1`, `pk2`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT referenced_table_name, unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 'self' ORDER BY referenced_table_name; REFERENCED_TABLE_NAME UNIQUE_CONSTRAINT_NAME grandparent1 PRIMARY grandparent2 PRIMARY self NULL DROP TABLE self, grandparent1, grandparent2; # # Bug#25722927 "NEWDD FK: ALTER TABLE CHANGE COLUMN TYPE SHOULD CHECK FK CONSTRAINT" # # # 1) Check how missing/dropped referencing and referenced columns # are handled. # # # 1.a) Missing referencing column. This problem is detected # during generated supported index processing. CREATE TABLE parent (pk INT PRIMARY KEY, j INT); CREATE TABLE child (fk INT, FOREIGN KEY (nocol) REFERENCES parent(pk)); ERROR 42000: Key column 'nocol' doesn't exist in table CREATE TABLE self (pk INT PRIMARY KEY, FOREIGN KEY (nocol) REFERENCES self(pk)); ERROR 42000: Key column 'nocol' doesn't exist in table CREATE TABLE child (fk INT, j INT); CREATE TABLE self (pk INT PRIMARY KEY, fk INT); ALTER TABLE child ADD FOREIGN KEY (nocol) REFERENCES parent(pk); ERROR 42000: Key column 'nocol' doesn't exist in table ALTER TABLE self ADD FOREIGN KEY (nocol) REFERENCES self(pk); ERROR 42000: Key column 'nocol' doesn't exist in table # # 1.b) Dropped referencing column. ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ALTER TABLE child DROP COLUMN fk; ERROR HY000: Cannot drop column 'fk': needed in a foreign key constraint 'child_ibfk_1' # Adding column with the same name at the same time should not help. ALTER TABLE child DROP COLUMN fk, ADD COLUMN fk INT; ERROR HY000: Cannot drop column 'fk': needed in a foreign key constraint 'child_ibfk_1' ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk); ALTER TABLE self DROP COLUMN fk; ERROR HY000: Cannot drop column 'fk': needed in a foreign key constraint 'self_ibfk_1' ALTER TABLE self DROP COLUMN fk, ADD COLUMN fk INT; ERROR HY000: Cannot drop column 'fk': needed in a foreign key constraint 'self_ibfk_1' # # 1.c) Missing referenced column. DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(nocol)); ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'child_ibfk_1' in the referenced table 'parent' DROP TABLE self; CREATE TABLE self (pk INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES self(nocol)); ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'self_ibfk_1' in the referenced table 'self' CREATE TABLE child (fk INT); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(nocol); ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'child_ibfk_1' in the referenced table 'parent' CREATE TABLE self (pk INT PRIMARY KEY, fk INT); ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(nocol); ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'self_ibfk_1' in the referenced table 'self' # # 1.d) Dropped referenced column. ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ALTER TABLE parent DROP COLUMN pk; ERROR HY000: Cannot drop column 'pk': needed in a foreign key constraint 'child_ibfk_1' of table 'child' # Adding column with the same name at the same time should not help. ALTER TABLE parent DROP COLUMN pk, ADD COLUMN pk INT; ERROR HY000: Cannot drop column 'pk': needed in a foreign key constraint 'child_ibfk_1' of table 'child' ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk); ALTER TABLE self DROP COLUMN pk; ERROR HY000: Cannot drop column 'pk': needed in a foreign key constraint 'self_ibfk_1' of table 'self' ALTER TABLE self DROP COLUMN pk, ADD COLUMN pk INT; ERROR HY000: Cannot drop column 'pk': needed in a foreign key constraint 'self_ibfk_1' of table 'self' # # 1.e) Special case. Attempt to create parent for orphan # foreign key which doesn't have matching column. DROP TABLES child, parent; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(nocol)); CREATE TABLE parent (pk INT PRIMARY KEY); ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'child_ibfk_1' in the referenced table 'parent' CREATE TABLE parent0 (pk INT PRIMARY KEY); RENAME TABLE parent0 TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'child_ibfk_1' in the referenced table 'parent' ALTER TABLE parent0 RENAME TO parent; ERROR HY000: Failed to add the foreign key constraint. Missing column 'nocol' for constraint 'child_ibfk_1' in the referenced table 'parent' SET FOREIGN_KEY_CHECKS=1; DROP TABLES child, parent0, self; # # 2) Handling of virtual columns in referencing and referenced # columns lists. # # # 2.a) Virtual columns in referencing columns list are not # supported. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (base INT, fk INT GENERATED ALWAYS AS (base+1) VIRTUAL, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'fk' which is not supported. CREATE TABLE self (pk INT PRIMARY KEY, base INT, fk INT GENERATED ALWAYS AS (base+1) VIRTUAL, FOREIGN KEY (fk) REFERENCES self(pk)); ERROR HY000: Foreign key 'self_ibfk_1' uses virtual column 'fk' which is not supported. CREATE TABLE child (base INT, fk INT GENERATED ALWAYS AS (base+1) VIRTUAL); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'fk' which is not supported. CREATE TABLE self (pk INT PRIMARY KEY, base INT, fk INT GENERATED ALWAYS AS (base+1) VIRTUAL); ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk); ERROR HY000: Foreign key 'self_ibfk_1' uses virtual column 'fk' which is not supported. # # 2.b) One should not be able to get virtual column in referencing # columns list by ALTERing column. DROP TABLE child, self; CREATE TABLE child (base INT, fk INT GENERATED ALWAYS AS (base+1) STORED, FOREIGN KEY (fk) REFERENCES parent(pk)); ALTER TABLE child MODIFY fk INT GENERATED ALWAYS AS (base+1) VIRTUAL; ERROR HY000: 'Changing the STORED status' is not supported for generated columns. CREATE TABLE self (pk INT PRIMARY KEY, base INT, fk INT GENERATED ALWAYS AS (base+1) STORED, FOREIGN KEY (fk) REFERENCES self(pk)); ALTER TABLE self MODIFY fk INT GENERATED ALWAYS AS (base+1) VIRTUAL; ERROR HY000: 'Changing the STORED status' is not supported for generated columns. # # 2.c) Virtual columns in referenced columns list are not # supported. DROP TABLE child, parent, self; CREATE TABLE parent (base INT, pk INT GENERATED ALWAYS AS (base+1) VIRTUAL, UNIQUE KEY(pk)); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'pk' which is not supported. CREATE TABLE child (fk INT); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'pk' which is not supported. CREATE TABLE self (base INT, pk INT GENERATED ALWAYS AS (base+1) VIRTUAL, fk INT, UNIQUE KEY(pk), FOREIGN KEY (fk) REFERENCES self(pk)); ERROR HY000: Foreign key 'self_ibfk_1' uses virtual column 'pk' which is not supported. CREATE TABLE self (base INT, pk INT GENERATED ALWAYS AS (base+1) VIRTUAL, fk INT, UNIQUE KEY(pk)); ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk); ERROR HY000: Foreign key 'self_ibfk_1' uses virtual column 'pk' which is not supported. # # 2.d) Again, one should not be able to get referenced virtual # column by ALTERing it. DROP TABLE child, parent, self; CREATE TABLE parent (base INT, pk INT GENERATED ALWAYS AS (base+1) STORED, UNIQUE KEY(pk)); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ALTER TABLE parent MODIFY pk INT GENERATED ALWAYS AS (base+1) VIRTUAL; ERROR HY000: 'Changing the STORED status' is not supported for generated columns. CREATE TABLE self (base INT, pk INT GENERATED ALWAYS AS (base+1) STORED, fk INT, UNIQUE KEY(pk), FOREIGN KEY (fk) REFERENCES self(pk)); ALTER TABLE self MODIFY pk INT GENERATED ALWAYS AS (base+1) VIRTUAL; ERROR HY000: 'Changing the STORED status' is not supported for generated columns. # # 2.e) Special case. Attempt to create parent for orphan # foreign key which has virtual column. DROP TABLES child, parent, self; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); CREATE TABLE parent (base INT, pk INT GENERATED ALWAYS AS (base+1) VIRTUAL, UNIQUE KEY(pk)); ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'pk' which is not supported. CREATE TABLE parent0 (base INT, pk INT GENERATED ALWAYS AS (base+1) VIRTUAL, UNIQUE KEY(pk)); RENAME TABLE parent0 TO parent; ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'pk' which is not supported. ALTER TABLE parent0 RENAME TO parent; ERROR HY000: Foreign key 'child_ibfk_1' uses virtual column 'pk' which is not supported. SET FOREIGN_KEY_CHECKS=1; DROP TABLES child, parent0; # # 3) Check how missing/dropped supporting index on referencing table # is handled. # # # 3.a) Normally, generated supporting index is automatically added # along with foreign key, so it can be missing only in some rare # corner case, for example, when generated index is automatically # converted to spatial index. CREATE TABLE parent (pk POINT SRID 0 NOT NULL, KEY(pk)); CREATE TABLE child (fk POINT SRID 0 NOT NULL, FOREIGN KEY(fk) REFERENCES parent(pk)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the foreign table 'child' CREATE TABLE child (fk POINT SRID 0 NOT NULL); ALTER TABLE child ADD FOREIGN KEY(fk) REFERENCES parent(pk); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the foreign table 'child' CREATE TABLE self (pk POINT SRID 0 NOT NULL, fk POINT SRID 0 NOT NULL, KEY(pk), FOREIGN KEY(fk) REFERENCES self(pk)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the foreign table 'self' CREATE TABLE self (pk POINT SRID 0 NOT NULL, fk POINT SRID 0 NOT NULL, KEY(pk)); ALTER TABLE self ADD FOREIGN KEY(fk) REFERENCES self(pk); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the foreign table 'self' # # 3.b) Attempt to drop supporting index should be prohibited. DROP TABLES self, child, parent; CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY(fk) REFERENCES parent(pk)); ALTER TABLE child DROP KEY fk; ERROR HY000: Cannot drop index 'fk': needed in a foreign key constraint CREATE TABLE self (pk INT PRIMARY KEY, fk INT, FOREIGN KEY(fk) REFERENCES self(pk)); ALTER TABLE self DROP KEY fk; ERROR HY000: Cannot drop index 'fk': needed in a foreign key constraint # However, we allow automatic dropping of generated index when new # explicit supporting index is added. ALTER TABLE child ADD KEY fk_s(fk); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `fk` int(11) DEFAULT NULL, KEY `fk_s` (`fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `parent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ALTER TABLE self ADD KEY fk_s(fk); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `pk` int(11) NOT NULL, `fk` int(11) DEFAULT NULL, PRIMARY KEY (`pk`), KEY `fk_s` (`fk`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `self` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci # Also dropping supporting index and providing replacement is fine. ALTER TABLE child DROP KEY fk_s, ADD COLUMN j INT, ADD KEY (fk, j); ALTER TABLE self DROP KEY fk_s, ADD COLUMN j INT, ADD KEY(fk, j); DROP TABLES self, child, parent; # # 4) Check how foreign keys involving partitioned tables are handled. # # # 4.a) Creation of partitioned child table, addition of foreign key to # partitioned table and attempt to partition child table in a # foreign key should all lead to errors (since InnoDB doesn't # support foreign keys involving partitioned tables yet). CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (pk INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)) PARTITION BY KEY (pk) PARTITIONS 20; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning CREATE TABLE child (pk INT PRIMARY KEY, fk INT) PARTITION BY KEY (pk) PARTITIONS 20; ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning DROP TABLE child; CREATE TABLE child (pk INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ALTER TABLE child PARTITION BY KEY (pk) PARTITIONS 20; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning # # 4.b) Attempt to partition parent table in a foreign key, # attempt to create table with foreign key referencing # partitioned table and addition of foreign key with # partitioned parent should all lead to errors as well. ALTER TABLE parent PARTITION BY KEY (pk) PARTITIONS 20; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning DROP TABLES child, parent; CREATE TABLE parent (pk INT PRIMARY KEY) PARTITION BY KEY (pk) PARTITIONS 20; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning CREATE TABLE child (fk INT); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning DROP TABLES child, parent; # # 4.c) Addition of partitioned parent for previously orphan foreign key # should result in error as well. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE orphan (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); SET FOREIGN_KEY_CHECKS=1; CREATE TABLE parent (pk INT PRIMARY KEY) PARTITION BY KEY (pk) PARTITIONS 20; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning CREATE TABLE parent0 (pk INT PRIMARY KEY) PARTITION BY KEY (pk) PARTITIONS 20; RENAME TABLE parent0 TO parent; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning ALTER TABLE parent0 RENAME TO parent; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning ALTER TABLE parent0 RENAME TO parent, ADD COLUMN j INT, ALGORITHM=COPY; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning ALTER TABLE parent0 RENAME TO parent, ADD COLUMN j INT, ALGORITHM=INPLACE; ERROR HY000: Foreign keys are not yet supported in conjunction with partitioning DROP TABLES orphan, parent0; # # 4.d) ALTER TABLE which ADD/DROP FOREIGN KEY and change table's # partitioning status at the same time. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (pk INT PRIMARY KEY, fk INT, CONSTRAINT c FOREIGN KEY (fk) REFERENCES parent(pk)); # Dropping foreign key and adding partitioning is OK. ALTER TABLE child DROP FOREIGN KEY c PARTITION BY KEY (pk) PARTITIONS 20; # Adding foreign key and removing partitioning is OK. ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk) REMOVE PARTITIONING; DROP TABLES child, parent; CREATE TABLE self (pk INT PRIMARY KEY, fk INT, CONSTRAINT c FOREIGN KEY (fk) REFERENCES self(pk)); # Dropping foreign key and adding partitioning is OK. ALTER TABLE self DROP FOREIGN KEY c PARTITION BY KEY (pk) PARTITIONS 20; # Adding foreign key and removing partitioning should be OK. # However, the below statement fails due to bug#28486106 in InnoDB code. ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk) REMOVE PARTITIONING; ERROR HY000: Cannot add foreign key constraint DROP TABLES self; # # 6) Check that we prohibit foreign keys with SET NULL action with # non-nullable referencing columns. # # # 6.1) Attempt to add foreign key with SET NULL action and # non-nullable column should lead to error. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk INT NOT NULL, CONSTRAINT c FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE SET NULL); ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'c' SET NULL CREATE TABLE child (fk INT NOT NULL, CONSTRAINT c FOREIGN KEY (fk) REFERENCES parent(pk) ON UPDATE SET NULL); ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'c' SET NULL CREATE TABLE child (fk INT NOT NULL); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE SET NULL; ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'child_ibfk_1' SET NULL ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk) ON UPDATE SET NULL; ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'child_ibfk_1' SET NULL DROP TABLE child; # Case of when column is implicitly made non-nullable due to PRIMARY # KEY should be handled in the same way. CREATE TABLE child (fk INT, PRIMARY KEY(fk), CONSTRAINT c FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE SET NULL); ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'c' SET NULL CREATE TABLE child (fk INT, PRIMARY KEY(fk), CONSTRAINT c FOREIGN KEY (fk) REFERENCES parent(pk) ON UPDATE SET NULL); ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'c' SET NULL CREATE TABLE child (fk INT); ALTER TABLE child ADD PRIMARY KEY (fk), ADD FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE SET NULL; ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'child_ibfk_1' SET NULL ALTER TABLE child ADD PRIMARY KEY (fk), ADD FOREIGN KEY (fk) REFERENCES parent(pk) ON UPDATE SET NULL; ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'child_ibfk_1' SET NULL DROP TABLE child; # # 6.2) Attempt to make referencing column non-nullable in existing # foreign key with SET NULL action should lead to error as well. CREATE TABLE child_one (fk INT, CONSTRAINT c FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE SET NULL); CREATE TABLE child_two (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk) ON DELETE SET NULL); ALTER TABLE child_one MODIFY COLUMN fk INT NOT NULL; ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'c' SET NULL ALTER TABLE child_two CHANGE COLUMN fk fk1 INT NOT NULL; ERROR HY000: Column 'fk1' cannot be NOT NULL: needed in a foreign key constraint 'child_two_ibfk_1' SET NULL # Case of when column is implicitly made non-nullable due addition # of PRIMARY KEY should be handled in the same way. ALTER TABLE child_one ADD PRIMARY KEY(fk); ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'c' SET NULL ALTER TABLE child_two ADD PRIMARY KEY(fk); ERROR HY000: Column 'fk' cannot be NOT NULL: needed in a foreign key constraint 'child_two_ibfk_1' SET NULL DROP TABLES child_one, child_two, parent; # # 7) Test that we check that referencing and referenced column types are # compatible. Such check should be performed for newly created foreign # keys and when we change types of columns in existing foreign keys. # # # 7.a) Attempt to create new foreign key between columns of incompatible # types should lead to error. This should happen even in # FOREIGN_KEY_CHECKS=0 mode. CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk CHAR(10), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk CHAR(10), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; CREATE TABLE child (fk CHAR(10)); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; CREATE TABLE self (pk INT PRIMARY KEY, fk CHAR(10), FOREIGN KEY (fk) REFERENCES self(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE self (pk INT PRIMARY KEY, fk CHAR(10), FOREIGN KEY (fk) REFERENCES self(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; CREATE TABLE self (pk INT PRIMARY KEY, fk CHAR(10)); ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE self ADD FOREIGN KEY (fk) REFERENCES self(pk); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; DROP TABLES self, child; # # 7.b) Attempt to change referencing or referenced column in existing # foreign key to incompatible type should lead to error. This # should also happen in FOREIGN_KEY_CHECKS=0 mode in general case # (there is exception for charset changes which we test below). CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ALTER TABLE child MODIFY fk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE parent MODIFY pk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE child MODIFY fk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE parent MODIFY pk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; CREATE TABLE self (pk INT PRIMARY KEY, fk INT, FOREIGN KEY (fk) REFERENCES self(pk)); ALTER TABLE self MODIFY fk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. ALTER TABLE self MODIFY pk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE self MODIFY fk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. ALTER TABLE self MODIFY pk CHAR(10); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'self_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; # Modifying types of both referencing and referenced columns to # to compatible types is OK. However FOREIGN_KEY_CHECKS=0 is needed # to avoid error about possible FK violation due to data conversion. SET FOREIGN_KEY_CHECKS=0; ALTER TABLE self MODIFY pk CHAR(10), MODIFY fk CHAR(10); SET FOREIGN_KEY_CHECKS=1; DROP TABLES child, parent, self; # # 7.c) Test compatibility checks for multi-column foreign keys. CREATE TABLE parent (pk1 INT, pk2 INT, PRIMARY KEY (pk1, pk2)); CREATE TABLE child (fk1 INT, fk2 CHAR(10), FOREIGN KEY (fk1, fk2) REFERENCES parent(pk1, pk2)); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk1 INT, fk2 CHAR(10)); ALTER TABLE child ADD FOREIGN KEY (fk1, fk2) REFERENCES parent(pk1, pk2); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE child; CREATE TABLE child (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent(pk1, pk2)); ALTER TABLE child MODIFY fk2 CHAR(10); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE parent MODIFY pk2 CHAR(10); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE child, parent; CREATE TABLE self (pk1 INT, pk2 INT, fk1 INT, fk2 CHAR(10), PRIMARY KEY (pk1, pk2), FOREIGN KEY (fk1, fk2) REFERENCES self(pk1, pk2)); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'self_ibfk_1' are incompatible. CREATE TABLE self (pk1 INT, pk2 INT, fk1 INT, fk2 CHAR(10), PRIMARY KEY (pk1, pk2)); ALTER TABLE self ADD FOREIGN KEY (fk1, fk2) REFERENCES self(pk1, pk2); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'self_ibfk_1' are incompatible. DROP TABLE self; CREATE TABLE self (pk1 INT, pk2 INT, fk1 INT, fk2 INT, PRIMARY KEY (pk1, pk2), FOREIGN KEY (fk1, fk2) REFERENCES self(pk1, pk2)); ALTER TABLE self MODIFY fk2 CHAR(10); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'self_ibfk_1' are incompatible. ALTER TABLE self MODIFY pk2 CHAR(10); ERROR HY000: Referencing column 'fk2' and referenced column 'pk2' in foreign key constraint 'self_ibfk_1' are incompatible. DROP TABLE self; # # 7.e) Test how compatibility rules work for various types. # Different engines have different rules, so the below # part of test is specific to InnoDB. # # We don't check compatibility for BLOB based types as they only # support prefix indexes which are not usable for foreign keys. # Also we don't provide coverage for legacy types. # # 7.e.I) For integer types both type size and signedness should match. CREATE TABLE parent (pk INT PRIMARY KEY); # Foreign keys over integer types are supported. CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; CREATE TABLE child (fk TINYINT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIGINT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk INT UNSIGNED, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE parent MODIFY pk INT UNSIGNED; CREATE TABLE child (fk INT UNSIGNED, FOREIGN KEY (fk) REFERENCES parent(pk)); ALTER TABLE child MODIFY fk INT; ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE child, parent; # Integer types are not compatible with most of other types # (we check types with same storage requirements as INT below). CREATE TABLE parent (pk INT PRIMARY KEY); CREATE TABLE child (fk BINARY(4), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARBINARY(3), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DECIMAL(8,0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIT(32), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. # Oddly enough, some integer types are compatible with some temporal # types, enums and sets. However, this is probably a bug and not a # feature, so we don't test it here. DROP TABLE parent; # # 7.e.II) For floating point types only the exact type matters. CREATE TABLE parent (pk DOUBLE PRIMARY KEY); # Though using such types in foreign key is EXTREMELY bad idea they # are supported. CREATE TABLE child (fk DOUBLE, FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. # Signedness doesn't matter. CREATE TABLE child (fk DOUBLE UNSIGNED, FOREIGN KEY (fk) REFERENCES parent(pk)); Warnings: Warning 1681 UNSIGNED for decimal and floating point data types is deprecated and support for it will be removed in a future release. DROP TABLES child, parent; # Floating point types are not compatible with other types. # (we check types with same storage requirements as FLOAT below). CREATE TABLE parent (pk FLOAT PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BINARY(4), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARBINARY(3), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DECIMAL(8,0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIME(2), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIT(32), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # # 7.e.III) Compatibility rules for DECIMAL type are broken. # # InnoDB considers this type to be binary string type. # So it doesn't take into account precision and scale. # And it is hard to imagine that comparing binary strings # representing DECIMAL(10,9) and DECIMAL(10,1) can work # correctly. Making this type compatible with other binary # string types, some temporals and BIT type is probably a # bad idea too. CREATE TABLE parent (pk DECIMAL(6,2) PRIMARY KEY); # Foreign keys over DECIMAL columns are supported. CREATE TABLE child (fk DECIMAL(6,2), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; # Signedness doesn't matter. CREATE TABLE child (fk DECIMAL(6,2) UNSIGNED, FOREIGN KEY (fk) REFERENCES parent(pk)); Warnings: Warning 1681 UNSIGNED for decimal and floating point data types is deprecated and support for it will be removed in a future release. DROP TABLE child; # DECIMAL type is not compatible with many other types. # (we check types with same storage requirements as DECIMAL(6,2) below). CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk CHAR(4) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARCHAR(3) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # # 7.e.IV) All string types are compatible with each other provided # that charset matches (there are exceptions to the latter # rule, see below). CREATE TABLE parent (pk CHAR(10) PRIMARY KEY); # Difference in size doesn't matter. CREATE TABLE child (fk CHAR(100), FOREIGN KEY (fk) REFERENCES parent(pk)); # Difference in type doesn't matter DROP TABLE child; CREATE TABLE child (fk VARCHAR(100), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLES child, parent; # Even VARCHARs which use different number of bytes to store length # are compatible. CREATE TABLE parent (pk VARCHAR(10) PRIMARY KEY); CREATE TABLE child (fk VARCHAR(100), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child, parent; # However both columns must use the same collation. CREATE TABLE parent (pk VARCHAR(10) CHARACTER SET utf8mb4 PRIMARY KEY); CREATE TABLE child (fk VARCHAR(100) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARCHAR(100) COLLATE utf8mb4_bin, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. # Binary strings are not compatible with non-binary strings. CREATE TABLE child (fk VARBINARY(40), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # But all binary string types are compatible. CREATE TABLE parent (pk VARBINARY(10) PRIMARY KEY); CREATE TABLE child (fk BINARY(100), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLES child, parent; # Non-binary string types are incompatible with non-string types. CREATE TABLE parent (pk CHAR(4) CHARACTER SET latin1 PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DECIMAL(8,0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIME(2), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIT(32), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE parent MODIFY pk CHAR(1) CHARACTER SET latin1; CREATE TABLE child (fk YEAR, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk ENUM('a') CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk SET('a') CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # Binary string types are incompatible with many non-string types. CREATE TABLE parent (pk BINARY(4) PRIMARY KEY); CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE parent MODIFY pk BINARY(1); CREATE TABLE child (fk YEAR, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk ENUM('a') CHARACTER SET binary, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk SET('a') CHARACTER SET binary, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. # Since we think that binary string compatibility with DECIMAL and some temporal types # is probably a bug, we don't cover it here. DROP TABLE parent; # # 7.e.V) Compatibility rules for some of temporal types are broken. # # InnoDB considers TIME, TIMESTAMP and DATETIME types to be # binary strings. As result they are compatible with each other # (no matter what scale is used), binary string, DECIMAL and BIT # types, which makes little sense. # YEAR and DATE types are considered to be integer types which # makes them compatible with some other integer types, enums and # sets, which is probably bad idea too. # # YEAR and DATE are only compatible with itself (and integer types, # enums and sets with the same storage size which is probably a bug); CREATE TABLE parent(pk DATE PRIMARY KEY); CREATE TABLE child (fk DATE, FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; CREATE TABLE child (fk YEAR, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BINARY(3), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARBINARY(2), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DECIMAL(6,0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIME(0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIT(24), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # TIME, TIMESTAMP and DATETIME types are compatible only # with other types which InnoDB considers binary strings. # Their scale doesn't matter (which is probably a bug). CREATE TABLE parent (pk TIMESTAMP PRIMARY KEY); CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk CHAR(4) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARCHAR(3) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DATE, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk ENUM('a'), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk SET('a'), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # # 7.e.VI) Columns of ENUM type are compatible if storage size is # the same. # # They are also compatible with some integer types, but it is not # clear if it is a bug or feature. # CREATE TABLE parent(pk ENUM('a') PRIMARY KEY); # Foreign key over ENUMs are supported, element names and count do # not matter provided that storage size is the same. CREATE TABLE child (fk ENUM('b','c'), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; # Storage size should match. CREATE TABLE child (fk ENUM('a1','a2','a3','a4','a5','a6','a7','a8','a9','a10','a11','a12','a13','a14','a15','a16','a17','a18','a19','a20','a21','a22','a23','a24','a25','a26','a27','a28','a29','a30','a31','a32','a33','a34','a35','a36','a37','a38','a39','a40','a41','a42','a43','a44','a45','a46','a47','a48','a49','a50','a51','a52','a53','a54','a55','a56','a57','a58','a59','a60','a61','a62','a63','a64','a65','a66','a67','a68','a69','a70','a71','a72','a73','a74','a75','a76','a77','a78','a79','a80','a81','a82','a83','a84','a85','a86','a87','a88','a89','a90','a91','a92','a93','a94','a95','a96','a97','a98','a99','a100','a101','a102','a103','a104','a105','a106','a107','a108','a109','a110','a111','a112','a113','a114','a115','a116','a117','a118','a119','a120','a121','a122','a123','a124','a125','a126','a127','a128','a129','a130','a131','a132','a133','a134','a135','a136','a137','a138','a139','a140','a141','a142','a143','a144','a145','a146','a147','a148','a149','a150','a151','a152','a153','a154','a155','a156','a157','a158','a159','a160','a161','a162','a163','a164','a165','a166','a167','a168','a169','a170','a171','a172','a173','a174','a175','a176','a177','a178','a179','a180','a181','a182','a183','a184','a185','a186','a187','a188','a189','a190','a191','a192','a193','a194','a195','a196','a197','a198','a199','a200','a201','a202','a203','a204','a205','a206','a207','a208','a209','a210','a211','a212','a213','a214','a215','a216','a217','a218','a219','a220','a221','a222','a223','a224','a225','a226','a227','a228','a229','a230','a231','a232','a233','a234','a235','a236','a237','a238','a239','a240','a241','a242','a243','a244','a245','a246','a247','a248','a249','a250','a251','a252','a253','a254','a255','a256'), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DATE, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BINARY(1), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARBINARY(1), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DECIMAL(2,0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIME, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIT(8), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # # 7.e.VII) Columns of SET type are compatible if storage size is # the same. # # They are also compatible with some integer types, but it is not # clear if it is a bug or feature. # CREATE TABLE parent(pk SET('a') PRIMARY KEY); # Foreign key over SETs are supported, element names and count do # not matter provided that storage size is the same. CREATE TABLE child (fk SET('b','c'), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; # Storage size should match. CREATE TABLE child (fk SET('a1','a2','a3','a4','a5','a6','a7','a8','a9'), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DATE, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BINARY(1), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARBINARY(1), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DECIMAL(2,0), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIME, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk TIMESTAMP, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk BIT(8), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # # 7.e.VIII) Columns of BIT type are compatible with each other # independently of size. # # They are considered binary strings so compatible with other # binary string types (which might make sense). They are also # compatible with some temporals and DECIMAL type, which makes # little sense. CREATE TABLE parent(pk BIT(32) PRIMARY KEY); # Column size doesn't matter. CREATE TABLE child (fk BIT(10), FOREIGN KEY (fk) REFERENCES parent(pk)); DROP TABLE child; CREATE TABLE child (fk INT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk DATE, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk CHAR(4) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARCHAR(3) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk FLOAT, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk ENUM('a'), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk SET('a'), FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE parent; # # 7.e.IX) In FOREIGN_KEY_CHECKS=0 mode InnoDB allows to change charsets # of string columns in existing foreign keys. Allowing such # temporary discrepancies is necessary as in general case there # is no way to change charset of both child and parent columns # simultaneously. Such discrepancies are still prohibited # in newly created foreign keys. CREATE TABLE parent (pk VARCHAR(10) CHARACTER SET latin1 PRIMARY KEY); CREATE TABLE child (fk VARCHAR(20) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); SET FOREIGN_KEY_CHECKS=0; ALTER TABLE parent MODIFY pk VARCHAR(10) CHARACTER SET utf8mb4; ALTER TABLE child MODIFY fk VARCHAR(20) CHARACTER SET utf8mb4; ALTER TABLE child MODIFY fk VARCHAR(20) CHARACTER SET latin1; ALTER TABLE parent MODIFY pk VARCHAR(10) CHARACTER SET latin1; DROP TABLE child; # Adding new foreign key with discrepancies is not allowed # even in FOREIGN_KEY_CHECKS=0 mode. CREATE TABLE child (fk VARCHAR(20) CHARACTER SET utf8mb4, FOREIGN KEY (fk) REFERENCES parent(pk)); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE child (fk VARCHAR(20) CHARACTER SET utf8mb4); ALTER TABLE child ADD FOREIGN KEY (fk) REFERENCES parent(pk); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLE child, parent; # One cannot create such discrepancy when adding parent to # orphan foreign key. CREATE TABLE child (fk VARCHAR(20) CHARACTER SET latin1, FOREIGN KEY (fk) REFERENCES parent(pk)); CREATE TABLE parent (pk VARCHAR(10) CHARACTER SET utf8mb4 PRIMARY KEY); ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. CREATE TABLE parent0 (pk VARCHAR(10) CHARACTER SET utf8mb4 PRIMARY KEY); RENAME TABLE parent0 TO parent; ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. DROP TABLES child, parent0; # This exception doesn't apply to binary strings though. CREATE TABLE parent (pk VARCHAR(10) CHARACTER SET binary PRIMARY KEY); CREATE TABLE child (fk VARCHAR(20) CHARACTER SET binary, FOREIGN KEY (fk) REFERENCES parent(pk)); ALTER TABLE parent MODIFY pk VARCHAR(10) CHARACTER SET utf8mb4; ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. ALTER TABLE child MODIFY fk VARCHAR(20) CHARACTER SET utf8mb4; ERROR HY000: Referencing column 'fk' and referenced column 'pk' in foreign key constraint 'child_ibfk_1' are incompatible. SET FOREIGN_KEY_CHECKS=1; DROP TABLES child, parent; # # WL#8910: Ensure foreign key error does not reveal information about # parent table for which user has no access privileges. # CREATE DATABASE wl8910db; USE wl8910db; #Set up tables. CREATE TABLE t1(fld1 INT PRIMARY KEY, fld2 INT) ENGINE=INNODB; CREATE TABLE t2(fld1 INT PRIMARY KEY, fld2 INT, CONSTRAINT fk2 FOREIGN KEY (fld1) REFERENCES t1 (fld1)) ENGINE=InnoDB; CREATE TABLE t3(fld1 INT PRIMARY KEY, fld2 INT) ENGINE=InnoDB; # Set up stored routines CREATE PROCEDURE p1() SQL SECURITY INVOKER INSERT INTO t2 (fld1, fld2) VALUES (1, 2); CREATE PROCEDURE p2() SQL SECURITY DEFINER INSERT INTO t2 (fld1, fld2) VALUES (1, 2); CREATE FUNCTION f1() RETURNS INT SQL SECURITY INVOKER BEGIN INSERT INTO t2 (fld1, fld2) VALUES (1, 2); RETURN 0; END| CREATE FUNCTION f2() RETURNS INT SQL SECURITY DEFINER BEGIN INSERT INTO t2 (fld1, fld2) VALUES (1, 2); RETURN 0; END| # Set up views. CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT * FROM t2; CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT * FROM t2; # Set up users and permissions. CREATE USER user1@localhost; CREATE USER user2@localhost; CREATE USER user3@localhost; GRANT INSERT (fld1, fld2) ON t2 TO user1@localhost; GRANT INSERT ON v1 TO user2@localhost; GRANT INSERT ON v2 TO user2@localhost; GRANT SYSTEM_USER ON *.* TO user2@localhost; GRANT SET_USER_ID ON *.* TO user2@localhost; GRANT EXECUTE ON PROCEDURE p1 TO user2@localhost; GRANT EXECUTE ON PROCEDURE p2 TO user2@localhost; GRANT EXECUTE ON FUNCTION f1 TO user2@localhost; GRANT EXECUTE ON FUNCTION f2 TO user2@localhost; connect con1, localhost, user1,,wl8910db; # Without patch, reveals parent table's information. INSERT INTO t2 (fld1, fld2) VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails # Warning displayed does not reveal parent table information. INSERT IGNORE INTO t2 (fld1, fld2) VALUES (1, 2); Warnings: Warning 1216 Cannot add or update a child row: a foreign key constraint fails SHOW WARNINGS; Level Code Message Warning 1216 Cannot add or update a child row: a foreign key constraint fails connection default; GRANT SELECT ON t1 TO user1@localhost; connection con1; INSERT INTO t2 (fld1, fld2) VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) connection default; ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (fld2) REFERENCES t3(fld1); connection con1; # Without patch, reveals parent table's information. INSERT INTO t2 (fld1, fld2) VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails # Warning displayed does not reveal parent table information. INSERT IGNORE INTO t2 (fld1, fld2) VALUES (1, 2); Warnings: Warning 1216 Cannot add or update a child row: a foreign key constraint fails SHOW WARNINGS; Level Code Message Warning 1216 Cannot add or update a child row: a foreign key constraint fails connection default; GRANT SELECT ON t3 TO user1@localhost; connection con1; INSERT INTO t2 (fld1, fld2) VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) connection default; GRANT INSERT (fld1, fld2) ON t2 TO user2@localhost; GRANT CREATE ROUTINE ON wl8910db.* TO user2@localhost; GRANT CREATE VIEW ON wl8910db.* TO user2@localhost; # Tests where DML reports FK constraint failure within Stored Routines. connect con2, localhost, user2,,wl8910db; # The SQL security for p1 is invoker where invoker lacks permission # to parent table, hence parent table information is not displayed. CALL p1(); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails # The SQL security p2 is definer, where the definer has access privilege # to the parent table, hence parent table information is displayed. CALL p2(); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) # The SQL security for f1 is invoker where invoker lacks permission # to parent table, hence parent table information is not displayed. SELECT f1(); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails # The SQL security f2 is definer, where the definer has access privilege # to the parent table, hence parent table information is displayed. SELECT f2(); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) # Test for DMLs on VIEWS. # The invoker does not have access to the parent table, hence the parent # table information is not displayed. INSERT INTO v1 VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails # DML on view executed within the definer context where the invoker does # not have access to the parent table, hence the parent table information # is not displayed. INSERT INTO v2 VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails connection default; GRANT SELECT ON t1 TO user2@localhost; GRANT SELECT ON t3 TO user2@localhost; connection con2; # DML on view executed within the definer context where the invoker # has access to the parent table, hence the parent table information # is displayed. INSERT INTO v2 VALUES (1, 2); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) # Tests with SET_USER_ID # Set up stored routines and views by user with SET_USER_ID # privilege. CREATE DEFINER=root@localhost PROCEDURE p3() SQL SECURITY DEFINER INSERT INTO t2 (fld1, fld2) VALUES (1, 2); CREATE DEFINER=root@localhost FUNCTION f3() RETURNS INT SQL SECURITY DEFINER BEGIN INSERT INTO t2 (fld1, fld2) VALUES (1, 2); RETURN 0; END| CREATE DEFINER=root@localhost SQL SECURITY DEFINER VIEW v3 AS SELECT * FROM t2; # Grant privileges for user3. connection default; GRANT EXECUTE ON PROCEDURE p3 TO user3@localhost; GRANT EXECUTE ON FUNCTION f3 TO user3@localhost; GRANT INSERT ON v3 TO user3@localhost; GRANT SELECT ON t1 TO user3@localhost; GRANT SELECT ON t3 TO user3@localhost; connect con3, localhost, user3,,wl8910db; # Since the execution happens in the definer 'root' user # context, the parent table informaton is exposed. CALL p3(); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) SELECT f3(); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) INSERT INTO v3 VALUES(4, 5); ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`wl8910db`.`t2`, CONSTRAINT `fk2` FOREIGN KEY (`fld1`) REFERENCES `t1` (`fld1`)) # Cleanup connection default; disconnect con1; disconnect con2; disconnect con3; DROP VIEW v1, v2, v3; DROP TABLE t2, t3, t1; DROP USER user1@localhost; DROP USER user2@localhost; DROP USER user3@localhost; DROP PROCEDURE p1; DROP PROCEDURE p2; DROP PROCEDURE p3; DROP FUNCTION f1; DROP FUNCTION f2; DROP FUNCTION f3; DROP DATABASE wl8910db; USE test; # # Bug #28122781 FOREIGN KEY REFERENCE OPTION RESTRICT IGNORED AFTER MYSQLDUMP AND RELOAD. # CREATE TABLE t1 ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY ); CREATE TABLE t2 ( t1_id INT NOT NULL, CONSTRAINT t2_fk FOREIGN KEY (t1_id) REFERENCES t1(id) ON UPDATE RESTRICT ); CREATE TABLE t3 ( t1_id INT NOT NULL, CONSTRAINT t3_fk FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE RESTRICT ); CREATE TABLE t4 ( t1_id INT NOT NULL, CONSTRAINT t4_fk FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE RESTRICT ON UPDATE RESTRICT ); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `t1_id` int(11) NOT NULL, KEY `t2_fk` (`t1_id`), CONSTRAINT `t2_fk` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( `t1_id` int(11) NOT NULL, KEY `t3_fk` (`t1_id`), CONSTRAINT `t3_fk` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t4; Table Create Table t4 CREATE TABLE `t4` ( `t1_id` int(11) NOT NULL, KEY `t4_fk` (`t1_id`), CONSTRAINT `t4_fk` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE TABLE_NAME IN ('t1', 't2', 't3', 't4'); CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test t2_fk def test PRIMARY NONE RESTRICT NO ACTION t2 t1 def test t3_fk def test PRIMARY NONE NO ACTION RESTRICT t3 t1 def test t4_fk def test PRIMARY NONE RESTRICT RESTRICT t4 t1 # dump tables t1, t2, t3, t3 DROP TABLE t1, t2, t3, t4; # reload dump SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `t1_id` int(11) NOT NULL, KEY `t2_fk` (`t1_id`), CONSTRAINT `t2_fk` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( `t1_id` int(11) NOT NULL, KEY `t3_fk` (`t1_id`), CONSTRAINT `t3_fk` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t4; Table Create Table t4 CREATE TABLE `t4` ( `t1_id` int(11) NOT NULL, KEY `t4_fk` (`t1_id`), CONSTRAINT `t4_fk` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE TABLE_NAME IN ('t1', 't2', 't3', 't4'); CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME UNIQUE_CONSTRAINT_CATALOG UNIQUE_CONSTRAINT_SCHEMA UNIQUE_CONSTRAINT_NAME MATCH_OPTION UPDATE_RULE DELETE_RULE TABLE_NAME REFERENCED_TABLE_NAME def test t2_fk def test PRIMARY NONE RESTRICT NO ACTION t2 t1 def test t3_fk def test PRIMARY NONE NO ACTION RESTRICT t3 t1 def test t4_fk def test PRIMARY NONE RESTRICT RESTRICT t4 t1 DROP TABLE t1, t2, t3, t4; # # Bug #27353767 "FOREIGN KEY IS ALWAYS IN LOWER CASE". # # Check that the way in which referencing and referenced column names in # foreign key definition are stored and shown in SHOW CREATE TABLE output # and I_S tables is with 5.7 and earlier versions. # # We always use version of name of referencing column which comes from # the definition of referencing table and not version from FOREIGN KEY # clause. # If referenced table exists than we use version of referenced column # name which comes from its definition, and not version from FOREIGN KEY # clause. CREATE TABLE parent (Pk VARCHAR(10) PRIMARY KEY); CREATE TABLE child (Fk VARCHAR(10), FOREIGN KEY (fK) REFERENCES parent(pK)); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `Fk` varchar(10) DEFAULT NULL, KEY `Fk` (`Fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `parent` (`Pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name Fk Pk DROP TABLE child; CREATE TABLE child (Fk VARCHAR(10)); ALTER TABLE child ADD FOREIGN KEY (fK) REFERENCES parent(pK); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `Fk` varchar(10) DEFAULT NULL, KEY `Fk` (`Fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `parent` (`Pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name Fk Pk # Ditto for self-referencing tables. CREATE TABLE self (Pk VARCHAR(10) PRIMARY KEY, Fk VARCHAR(10), FOREIGN KEY (fK) REFERENCES self(pK)); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `Pk` varchar(10) NOT NULL, `Fk` varchar(10) DEFAULT NULL, PRIMARY KEY (`Pk`), KEY `Fk` (`Fk`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `self` (`Pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='self'; column_name referenced_column_name Fk Pk DROP TABLE self; CREATE TABLE self (Pk VARCHAR(10) PRIMARY KEY, Fk VARCHAR(10)); ALTER TABLE self ADD FOREIGN KEY (fK) REFERENCES self(pK); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `Pk` varchar(10) NOT NULL, `Fk` varchar(10) DEFAULT NULL, PRIMARY KEY (`Pk`), KEY `Fk` (`Fk`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `self` (`Pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='self'; column_name referenced_column_name Fk Pk # # If column name is changed (even to equivalent one) then the name shown # in foreign key definition is updated too. ALTER TABLE parent CHANGE COLUMN Pk PK VARCHAR(20); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `Fk` varchar(10) DEFAULT NULL, KEY `Fk` (`Fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `parent` (`PK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name Fk PK ALTER TABLE child CHANGE COLUMN Fk FK VARCHAR(20); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `FK` varchar(20) DEFAULT NULL, KEY `Fk` (`FK`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`FK`) REFERENCES `parent` (`PK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name FK PK # Ditto for self-referencing tables. ALTER TABLE self CHANGE COLUMN Pk PK VARCHAR(20); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `PK` varchar(20) NOT NULL, `Fk` varchar(10) DEFAULT NULL, PRIMARY KEY (`PK`), KEY `Fk` (`Fk`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `self` (`PK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='self'; column_name referenced_column_name Fk PK ALTER TABLE self CHANGE COLUMN Fk FK VARCHAR(20); SHOW CREATE TABLE self; Table Create Table self CREATE TABLE `self` ( `PK` varchar(20) NOT NULL, `FK` varchar(20) DEFAULT NULL, PRIMARY KEY (`PK`), KEY `Fk` (`FK`), CONSTRAINT `self_ibfk_1` FOREIGN KEY (`FK`) REFERENCES `self` (`PK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='self'; column_name referenced_column_name FK PK DROP TABLE self; # # Referenced column names are preserved when referenced table is dropped # (which is possible in FOREIGN_KEY_CHECKS = 0 mode). SET FOREIGN_KEY_CHECKS=0; DROP TABLE parent; SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `FK` varchar(20) DEFAULT NULL, KEY `Fk` (`FK`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`FK`) REFERENCES `parent` (`PK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name FK PK # # Addition of parent doesn't change the referenced column names. CREATE TABLE parent (pk VARCHAR(10) PRIMARY KEY); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `FK` varchar(20) DEFAULT NULL, KEY `Fk` (`FK`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`FK`) REFERENCES `parent` (`PK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name FK PK DROP TABLES child, parent; # # We use version of referenced column name coming from FOREIGN KEY clause # when orphan foreign key is created (as referenced table doesn't exist). # # Oddly, 5.7 uses version of referencing column name coming from FOREIGN # KEY clause when orphan FK is added via ALTER TABLE (but not CREATE # TABLE). This means that in 5.7 there is discrepancy between CREATE and # ALTER TABLE behavior in this case. # In 8.0 we are consistent and stick to CREATE TABLE behavior in such # cases. CREATE TABLE child (Fk VARCHAR(10), FOREIGN KEY (fK) REFERENCES parent(pK)); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `Fk` varchar(10) DEFAULT NULL, KEY `Fk` (`Fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `parent` (`pK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name Fk pK DROP TABLE child; CREATE TABLE child (Fk VARCHAR(10)); ALTER TABLE child ADD FOREIGN KEY (fK) REFERENCES parent(pK); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `Fk` varchar(10) DEFAULT NULL, KEY `Fk` (`Fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `parent` (`pK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name Fk pK # # Addition of parent doesn't change the referenced column names. CREATE TABLE parent (pk VARCHAR(10) PRIMARY KEY); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `Fk` varchar(10) DEFAULT NULL, KEY `Fk` (`Fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`Fk`) REFERENCES `parent` (`pK`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT column_name, referenced_column_name FROM information_schema.key_column_usage WHERE referenced_table_schema='test' AND referenced_table_name='parent'; column_name referenced_column_name Fk pK SET FOREIGN_KEY_CHECKS=1; DROP TABLES child, parent; # # Test for bug#29173134 "FOREIGN KEY CONSTRAINT NAMES TAKING INDEX NAME". # # # Original test case. CREATE TABLE t1 (id INT PRIMARY KEY); CREATE TABLE t2 (t1id INT, FOREIGN KEY fk_index (t1id) REFERENCES t1 (id)); CREATE TABLE t3 (t1id INT, FOREIGN KEY fk_index (t1id) REFERENCES t1 (id)); SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `t1id` int(11) DEFAULT NULL, KEY `fk_index` (`t1id`), CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1id`) REFERENCES `t1` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( `t1id` int(11) DEFAULT NULL, KEY `fk_index` (`t1id`), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1id`) REFERENCES `t1` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT CONSTRAINT_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE TABLE_NAME IN ('t2', 't3') ORDER BY CONSTRAINT_NAME; CONSTRAINT_NAME TABLE_NAME t2_ibfk_1 t2 t3_ibfk_1 t3 # # Let us check what foreign key names are used in different situations. CREATE TABLE t4 (fk1 INT, fk2 INT, fk3 INT, fk4 INT, FOREIGN KEY (fk1) REFERENCES t1 (id), CONSTRAINT c FOREIGN KEY (fk2) REFERENCES t1 (id), FOREIGN KEY d (fk3) REFERENCES t1 (id), CONSTRAINT e FOREIGN KEY f (fk4) REFERENCES t1 (id)); SHOW CREATE TABLE t4; Table Create Table t4 CREATE TABLE `t4` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, `fk3` int(11) DEFAULT NULL, `fk4` int(11) DEFAULT NULL, KEY `fk1` (`fk1`), KEY `c` (`fk2`), KEY `d` (`fk3`), KEY `e` (`fk4`), CONSTRAINT `c` FOREIGN KEY (`fk2`) REFERENCES `t1` (`id`), CONSTRAINT `e` FOREIGN KEY (`fk4`) REFERENCES `t1` (`id`), CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`fk1`) REFERENCES `t1` (`id`), CONSTRAINT `t4_ibfk_2` FOREIGN KEY (`fk3`) REFERENCES `t1` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE TABLE_NAME = 't4' ORDER BY CONSTRAINT_NAME; CONSTRAINT_NAME c e t4_ibfk_1 t4_ibfk_2 # Clean-up. DROP TABLES t1, t2, t3, t4; # # Bug #11756183 "FOREIGN KEYS MAY DISAPPEAR AFTER ALTER TABLE RENAME". # Bug #18713399 "FK CHILD TABLE CANNOT BE CREATED: PROBLEMS AFTER TABLE RENAME" # CREATE TABLE parent (pk INT PRIMARY KEY); INSERT INTO parent VALUES (1); CREATE TABLE child (fk INT, b INT, FOREIGN KEY (fk) REFERENCES parent (pk)); INSERT INTO child VALUES (1, 1); SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `fk` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, KEY `fk` (`fk`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `parent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci # We use ALGORITHM=COPY to ensure that the below ALTER is executed # using COPY algorithm even if changing column datatype becomes # in-place operation. ALTER TABLE child MODIFY COLUMN b BIGINT, RENAME TO child_renamed, ALGORITHM=COPY; # The foreign key should be still in SHOW CREATE TABLE output. SHOW CREATE TABLE child_renamed; Table Create Table child_renamed CREATE TABLE `child_renamed` ( `fk` int(11) DEFAULT NULL, `b` bigint(20) DEFAULT NULL, KEY `fk` (`fk`), CONSTRAINT `child_renamed_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `parent` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci # Removal of parent row should not be allowed. DELETE FROM parent WHERE pk = 1; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child_renamed`, CONSTRAINT `child_renamed_ibfk_1` FOREIGN KEY (`fk`) REFERENCES `parent` (`pk`)) DROP TABLE child_renamed; # Part of test covering bug#18713399. The below CREATE TABLE statement # should not fail due to duplicate foreign key name. CREATE TABLE child (fk INT, b INT, FOREIGN KEY (fk) REFERENCES parent (pk)); DROP TABLES child, parent; # # Bug #18199504 "AUTO-NAMING OF FOREIGN KEYS SEEMS BROKEN WHEN # MULTI-OPERATION ALTER IS USED". # CREATE TABLE parent (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c CHAR(32)); CREATE TABLE uncle (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c CHAR(32)); CREATE TABLE child (parent_id INT, c CHAR(32), FOREIGN KEY (parent_id) REFERENCES parent (id)); # Turn off foreign key checking so we can add foreign key using # inplace algorithm. SET FOREIGN_KEY_CHECKS=0; # The problem occured when a foreign key was added by ALTER TABLE # executed using inplace algorithm which still did table rebuild # internally. So we drop column to make operation non-instant for # sure. ALTER TABLE child ADD COLUMN uncle_id INT, DROP COLUMN c, ADD CONSTRAINT FOREIGN KEY (uncle_id) REFERENCES uncle (id), ALGORITHM=INPLACE; SET FOREIGN_KEY_CHECKS=1; SHOW CREATE TABLE child; Table Create Table child CREATE TABLE `child` ( `parent_id` int(11) DEFAULT NULL, `uncle_id` int(11) DEFAULT NULL, KEY `parent_id` (`parent_id`), KEY `uncle_id` (`uncle_id`), CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`), CONSTRAINT `child_ibfk_2` FOREIGN KEY (`uncle_id`) REFERENCES `uncle` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci DROP TABLES child, parent, uncle; # # Bug #28480149 "UPGRADE FAIL: FAILED TO ADD THE FOREIGN KEY # CONSTRAINT. MISSING INDEX FOR CONSTR". # # When InnoDB SE checks if a key can serve as a parent key for a foreign # key it takes into account columns from hidden part of the key. This # hidden part consists of primary key columns which are implicitly # added by InnoDB to non-primary keys. # # See dd_upgrade_test test for coverage of upgrade process for such # foreign keys. # CREATE TABLE parent (pk INT PRIMARY KEY, a INT, b INT, KEY(a), UNIQUE(b)); # This works both for non-unique and unique keys. CREATE TABLE child1 (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent (a, pk)); CREATE TABLE child2 (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent (b, pk)); DROP TABLES child1, child2; # This also works when foreign keys are added by ALTER TABLE. CREATE TABLE child1 (fk1 INT, fk2 INT); ALTER TABLE child1 ADD FOREIGN KEY (fk1, fk2) REFERENCES parent (a, pk); CREATE TABLE child2 (fk1 INT, fk2 INT); ALTER TABLE child2 ADD FOREIGN KEY (fk1, fk2) REFERENCES parent (b, pk); DROP TABLES child1, child2, parent; # And for complex multi-column cases too. CREATE TABLE parent (a INT, b INT, c INT, PRIMARY KEY (a,b), KEY(c, a)); CREATE TABLE child (fk1 INT, fk2 INT, fk3 INT, FOREIGN KEY (fk1, fk2, fk3) REFERENCES parent (c, a, b)); DROP TABLES child, parent; # Moreover, this works for keys which are promoted to primary. CREATE TABLE parent (u INT NOT NULL, a INT, b INT, UNIQUE(u), KEY(a), UNIQUE(b)); CREATE TABLE child1 (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent (a, u)); CREATE TABLE child2 (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent (b, u)); DROP TABLES child1, child2, parent; # Also works correctly when parent table is altered. CREATE TABLE parent (pk INT PRIMARY KEY, a INT, KEY k1(a, pk), UNIQUE k2(a)); CREATE TABLE child (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent (a, pk)); ALTER TABLE parent DROP KEY k1; DROP TABLES child, parent; # And when we add parent table to previously orphan foreign key. SET FOREIGN_KEY_CHECKS=0; CREATE TABLE child (fk1 INT, fk2 INT, CONSTRAINT c FOREIGN KEY (fk1, fk2) REFERENCES parent (a, pk)); SET FOREIGN_KEY_CHECKS=1; CREATE TABLE parent (pk INT PRIMARY KEY, a INT, UNIQUE ua(a)); SELECT constraint_name, unique_constraint_name FROM information_schema.referential_constraints WHERE constraint_schema='test' AND constraint_name='c'; CONSTRAINT_NAME UNIQUE_CONSTRAINT_NAME c ua DROP TABLES child, parent; # However, columns which are implicitly added by InnoDB as hidden # elements to the primary key are not considered when searching for # parent key (because primary key contains hidden system DB_TRX_ID, # DB_ROLL_PTR columns before hidden normal columns). CREATE TABLE parent (pk INT PRIMARY KEY, a INT); CREATE TABLE child (fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES parent (pk, a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' DROP TABLE parent; # Hidden parts which are column prefixes (because primary key has prefix # parts [sic!]) are not allowed as parent key parts. CREATE TABLE parent (a CHAR(10), b int, KEY(b), PRIMARY KEY (a(5))); CREATE TABLE child (fk1 int, fk2 CHAR(10), FOREIGN KEY (fk1, fk2) REFERENCES parent (b, a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' DROP TABLE parent; # Moreover, even hidden parts for full columns are not allowed if # primary key contains prefix parts. This was supported in 5.7. CREATE TABLE parent (a INT, b CHAR(10), c int, KEY(c), PRIMARY KEY (a, b(5))); CREATE TABLE child (fk1 int, fk2 int, FOREIGN KEY (fk1, fk2) REFERENCES parent (c, a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'child_ibfk_1' in the referenced table 'parent' DROP TABLE parent; # # Now similar tests for self-referencing foreign keys. # CREATE TABLE self1 (pk INT PRIMARY KEY, a INT, fk1 INT, fk2 INT, KEY(a), FOREIGN KEY (fk1, fk2) REFERENCES self1 (a, pk)); CREATE TABLE self2 (pk INT PRIMARY KEY, b INT, fk1 INT, fk2 INT, UNIQUE(b), FOREIGN KEY (fk1, fk2) REFERENCES self2 (b, pk)); DROP TABLES self1, self2; CREATE TABLE self1 (pk INT PRIMARY KEY, a INT, fk1 INT, fk2 INT, KEY(a)); ALTER TABLE self1 ADD FOREIGN KEY (fk1, fk2) REFERENCES self1 (a, pk); CREATE TABLE self2 (pk INT PRIMARY KEY, b INT, fk1 INT, fk2 INT, UNIQUE(b)); ALTER TABLE self2 ADD FOREIGN KEY (fk1, fk2) REFERENCES self2 (b, pk); DROP TABLES self1, self2; # Test for complex multi-column case. CREATE TABLE self (a INT, b INT, c INT, fk1 INT, fk2 INT, fk3 INT, PRIMARY KEY (a,b), KEY(c, a), FOREIGN KEY (fk1, fk2, fk3) REFERENCES self (c, a, b)); DROP TABLE self; # Test for removing parent key. CREATE TABLE self (pk INT PRIMARY KEY, a INT, fk1 INT, fk2 INT, KEY k1(a, pk), UNIQUE k2(a), FOREIGN KEY (fk1, fk2) REFERENCES self (a, pk)); ALTER TABLE self DROP KEY k1; DROP TABLE self; # But again this is not supposed to work for hidden columns added to # primary key. CREATE TABLE self (pk INT PRIMARY KEY, a INT, fk1 INT, fk2 INT, FOREIGN KEY (fk1, fk2) REFERENCES self (pk, a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' # Hidden parts which are column prefixes should not work. CREATE TABLE self (a CHAR(10), b int, fk1 int, fk2 CHAR(10), KEY(b), PRIMARY KEY (a(5)), FOREIGN KEY (fk1, fk2) REFERENCES self (b, a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' # Hidden parts for full columns are not allowed either if # primary key contains prefix parts. This was supported in 5.7. CREATE TABLE self (a INT, b CHAR(10), c int, fk1 int, fk2 int, KEY(c), PRIMARY KEY (a, b(5)), FOREIGN KEY (fk1, fk2) REFERENCES self (c, a)); ERROR HY000: Failed to add the foreign key constraint. Missing index for constraint 'self_ibfk_1' in the referenced table 'self' # # Bug#21308781 "DROP FOREIGN KEY LEAD TO INCONSISTENT TABLE STRUCTURE # ON MASTER AND SLAVE". # CREATE TABLE t1(pk INT PRIMARY KEY); CREATE TABLE t2(pk INT PRIMARY KEY); CREATE TABLE t3(fk1 INT, fk2 INT, KEY k1(fk1), CONSTRAINT a FOREIGN KEY (fk1) REFERENCES t1(pk), CONSTRAINT b FOREIGN KEY (fk2) REFERENCES t2(pk)); ALTER TABLE t3 DROP KEY k1, DROP FOREIGN KEY b, ALGORITHM=COPY; ERROR HY000: Cannot drop index 'k1': needed in a foreign key constraint # Failed ALTER TABLE should have left table intact! SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( `fk1` int(11) DEFAULT NULL, `fk2` int(11) DEFAULT NULL, KEY `k1` (`fk1`), KEY `b` (`fk2`), CONSTRAINT `a` FOREIGN KEY (`fk1`) REFERENCES `t1` (`pk`), CONSTRAINT `b` FOREIGN KEY (`fk2`) REFERENCES `t2` (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci DROP TABLES t3, t2, t1;