From e8b05ce503dffc2d95d1583b7c89403d320e263c Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 8 Sep 2020 17:24:08 +0530 Subject: [PATCH] MDEV-23675 Assertion `pos < table->n_def' fails in dict_table_get_nth_col - During insertion of clustered inde, InnoDB does the check for foreign key constraints. It rebuild the tuple based on foreign column names when there is no foreign index. While rebuilding, InnoDB should ignore the dropped columns. --- mysql-test/suite/innodb/r/foreign_key.result | 13 +++++++++++++ mysql-test/suite/innodb/t/foreign_key.test | 14 ++++++++++++++ storage/innobase/row/row0ins.cc | 10 ++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index bd40f98ef65..2facbccc466 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -755,4 +755,17 @@ DROP TABLE t1; CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +# +# MDEV-23675 Assertion `pos < table->n_def' in dict_table_get_nth_col +# +CREATE TABLE t1 (pk int PRIMARY KEY, a INT, b INT, c INT, KEY(c), +FOREIGN KEY fx (b) REFERENCES t1 (c)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,0,10,10); +ALTER TABLE t1 DROP a, ALGORITHM=INSTANT; +SET FOREIGN_KEY_CHECKS= 0; +DROP INDEX fx ON t1; +INSERT INTO t1 VALUES (2,11,11); +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=DEFAULT; # End of 10.4 tests diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 9207fce6525..dab0736f712 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -741,6 +741,20 @@ DROP TABLE t1; CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; +--echo # +--echo # MDEV-23675 Assertion `pos < table->n_def' in dict_table_get_nth_col +--echo # +CREATE TABLE t1 (pk int PRIMARY KEY, a INT, b INT, c INT, KEY(c), +FOREIGN KEY fx (b) REFERENCES t1 (c)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,0,10,10); +ALTER TABLE t1 DROP a, ALGORITHM=INSTANT; +SET FOREIGN_KEY_CHECKS= 0; +DROP INDEX fx ON t1; +INSERT INTO t1 VALUES (2,11,11); +DROP TABLE t1; +SET FOREIGN_KEY_CHECKS=DEFAULT; + -- echo # End of 10.4 tests --source include/wait_until_count_sessions.inc diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 9c913b0c9f2..a28489062b0 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1908,8 +1908,14 @@ bool row_ins_foreign_index_entry(dict_foreign_t *foreign, { for (ulint j= 0; j < index->n_fields; j++) { - const char *col_name= dict_table_get_col_name( - index->table, dict_index_get_nth_col_no(index, j)); + const dict_col_t *col= dict_index_get_nth_col(index, j); + + /* A clustered index may contain instantly dropped columns, + which must be skipped. */ + if (col->is_dropped()) + continue; + + const char *col_name= dict_table_get_col_name(index->table, col->ind); if (0 == innobase_strcasecmp(col_name, foreign->foreign_col_names[i])) { dfield_copy(&ref_entry->fields[i], &entry->fields[j]);