mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Bug #23533396 ASSERTION !M_PREBUILT->TRX->CHECK_FOREIGNS
Analysis: ======== A foreign key constraint cannot reference a secondary index defined on a generated virtual column. While adding new index/drop existing column, server internally drops the internal foreign key index and it leads to choose the virtual secondary index as foreign key index. But innodb doesn't allow foreign key constraint reference to secondary virtual index. Fix: === Allow foreign key constraint refer to secondary index defined on a generated virutal column. Reviewed-by: Jimmy Yang<jimmy.yang@oracle.com> RB: 13586
This commit is contained in:
committed by
Marko Mäkelä
parent
93078c9cb1
commit
a6adf567fd
@@ -590,3 +590,101 @@ SELECT * FROM t2;
|
|||||||
fld1 fld2
|
fld1 fld2
|
||||||
1 1
|
1 1
|
||||||
DROP TABLE t2, t1;
|
DROP TABLE t2, t1;
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2), FOREIGN KEY(f1) REFERENCES t1(f1))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL f1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
f1 f2
|
||||||
|
1 1
|
||||||
|
INSERT INTO t2(f1) VALUES(2);
|
||||||
|
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`))
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2), FOREIGN KEY(f1) REFERENCES t1(f1)
|
||||||
|
ON UPDATE CASCADE)ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL f1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
f1 f2
|
||||||
|
1 1
|
||||||
|
UPDATE t1 SET f1 = 2 WHERE f1 = 1;
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL f1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
f1 f2
|
||||||
|
2 2
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
ALTER TABLE t2 ADD FOREIGN KEY (f1) REFERENCES t1(f1)
|
||||||
|
ON UPDATE CASCADE, ALGORITHM=INPLACE;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL f1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
f1 f2
|
||||||
|
3 3
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
ALTER TABLE t2 ADD FOREIGN KEY (f1) REFERENCES t1(f1)
|
||||||
|
ON UPDATE CASCADE, ALGORITHM=COPY;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL f1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
f1 f2
|
||||||
|
3 3
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
CREATE TABLE t1(f1 INT NOT NULL, PRIMARY KEY(f1))ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2(f1 INT NOT NULL, f2 INT AS (1) VIRTUAL,
|
||||||
|
f3 INT AS (2) VIRTUAL,
|
||||||
|
FOREIGN KEY idx (f1) REFERENCES t1(f1) ON UPDATE CASCADE,
|
||||||
|
KEY idx1 (f2, f1, f3))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
ALTER TABLE t2 DROP COLUMN f2, ALGORITHM=INPLACE;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f3 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL idx1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f3 FROM t2;
|
||||||
|
f1 f3
|
||||||
|
3 2
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
CREATE TABLE t1(f1 INT NOT NULL, PRIMARY KEY(f1))ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2(f1 INT NOT NULL, f2 INT AS (1) VIRTUAL,
|
||||||
|
f3 INT AS (2) VIRTUAL,
|
||||||
|
FOREIGN KEY idx (f1) REFERENCES t1(f1) ON UPDATE CASCADE,
|
||||||
|
KEY idx1 (f2, f1, f3))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
ALTER TABLE t2 DROP COLUMN f2, ALGORITHM=COPY;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f3 FROM t2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t2 index NULL idx1 9 NULL 1 Using index
|
||||||
|
SELECT f1, f3 FROM t2;
|
||||||
|
f1 f3
|
||||||
|
3 2
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
@@ -490,3 +490,89 @@ UPDATE t1 SET fld1= 2;
|
|||||||
SELECT fld2 FROM t2;
|
SELECT fld2 FROM t2;
|
||||||
SELECT * FROM t2;
|
SELECT * FROM t2;
|
||||||
DROP TABLE t2, t1;
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
# Foreign key constraint references to virtual index
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2), FOREIGN KEY(f1) REFERENCES t1(f1))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
--error ER_NO_REFERENCED_ROW_2
|
||||||
|
INSERT INTO t2(f1) VALUES(2);
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
# Update foreign key constraint references to virtual index
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2), FOREIGN KEY(f1) REFERENCES t1(f1)
|
||||||
|
ON UPDATE CASCADE)ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
UPDATE t1 SET f1 = 2 WHERE f1 = 1;
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
# Add foreign key constraint via inplace alter references to virtual index
|
||||||
|
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
ALTER TABLE t2 ADD FOREIGN KEY (f1) REFERENCES t1(f1)
|
||||||
|
ON UPDATE CASCADE, ALGORITHM=INPLACE;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
# Add foreign key constraint via copy alter references to virtual index
|
||||||
|
|
||||||
|
CREATE TABLE t1 (f1 INT NOT NULL PRIMARY KEY)ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2 (f1 INT NOT NULL, f2 INT AS (f1) VIRTUAL,
|
||||||
|
KEY (f1, f2))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
ALTER TABLE t2 ADD FOREIGN KEY (f1) REFERENCES t1(f1)
|
||||||
|
ON UPDATE CASCADE, ALGORITHM=COPY;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f2 FROM t2;
|
||||||
|
SELECT f1, f2 FROM t2;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
# Drop column via inplace alter which triggers to remove the FK index idx
|
||||||
|
|
||||||
|
CREATE TABLE t1(f1 INT NOT NULL, PRIMARY KEY(f1))ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2(f1 INT NOT NULL, f2 INT AS (1) VIRTUAL,
|
||||||
|
f3 INT AS (2) VIRTUAL,
|
||||||
|
FOREIGN KEY idx (f1) REFERENCES t1(f1) ON UPDATE CASCADE,
|
||||||
|
KEY idx1 (f2, f1, f3))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
ALTER TABLE t2 DROP COLUMN f2, ALGORITHM=INPLACE;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f3 FROM t2;
|
||||||
|
SELECT f1, f3 FROM t2;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
# Drop column via copy alter which triggers to remove the FK index idx
|
||||||
|
|
||||||
|
CREATE TABLE t1(f1 INT NOT NULL, PRIMARY KEY(f1))ENGINE=INNODB;
|
||||||
|
CREATE TABLE t2(f1 INT NOT NULL, f2 INT AS (1) VIRTUAL,
|
||||||
|
f3 INT AS (2) VIRTUAL,
|
||||||
|
FOREIGN KEY idx (f1) REFERENCES t1(f1) ON UPDATE CASCADE,
|
||||||
|
KEY idx1 (f2, f1, f3))ENGINE=INNODB;
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
ALTER TABLE t2 DROP COLUMN f2, ALGORITHM=COPY;
|
||||||
|
UPDATE t1 SET f1 = 3;
|
||||||
|
EXPLAIN SELECT f1, f3 FROM t2;
|
||||||
|
SELECT f1, f3 FROM t2;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
@@ -1296,7 +1296,6 @@ innobase_find_fk_index(
|
|||||||
|
|
||||||
while (index != NULL) {
|
while (index != NULL) {
|
||||||
if (!(index->type & DICT_FTS)
|
if (!(index->type & DICT_FTS)
|
||||||
&& !dict_index_has_virtual(index)
|
|
||||||
&& dict_foreign_qualify_index(
|
&& dict_foreign_qualify_index(
|
||||||
table, col_names, columns, n_cols,
|
table, col_names, columns, n_cols,
|
||||||
index, NULL, true, 0,
|
index, NULL, true, 0,
|
||||||
|
Reference in New Issue
Block a user