Skip to content

Commit 4a1c662

Browse files
committed
MDEV-18775 Fix ALTER TABLE error handling for DROP INDEX
On an error (such as when an index cannot be dropped due to FOREIGN KEY constraints), the field dict_index_t::to_be_dropped was only being cleared in debug builds, even though the field is available and being used also in non-debug builds. This was a regression that was introduced by myself originally in MySQL 5.7.6 and later merged to MariaDB 10.2.2, in mysql/mysql-server@d39898d An error manifested itself in the MariaDB Server 10.4 non-debug build, involving instant ADD or DROP column. Because an earlier failed ALTER TABLE operation incorrectly left the dict_index_t::to_be_dropped flag set, the column pointers of the index fields would fail to be adjusted for instant ADD or DROP column (MDEV-15562). The instant ADD COLUMN in MariaDB Server 10.3 is unlikely to be affected by a similar scenario, because dict_table_t::instant_add_column() in 10.3 is applying the transformations to all indexes, not skipping to-be-dropped ones.
1 parent 003b507 commit 4a1c662

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

mysql-test/suite/innodb/r/alter_table.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,18 @@ Warnings:
3838
Warning 1105 ORDER BY ignored as there is a user-defined clustered index in the table 't1'
3939
DROP TABLE t1;
4040
SET sql_mode=DEFAULT;
41+
#
42+
# MDEV-18775 Server crashes in dict_table_t::instant_column
43+
# upon ADD COLUMN
44+
#
45+
CREATE TABLE tx (pk INT PRIMARY KEY) ENGINE=InnoDB;
46+
CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a), FOREIGN KEY (a) REFERENCES tx (pk)) ENGINE=InnoDB;
47+
SET FOREIGN_KEY_CHECKS=OFF;
48+
ALTER TABLE t1 DROP a;
49+
ERROR HY000: Cannot drop column 'a': needed in a foreign key constraint 'test/t1_ibfk_1'
50+
SET FOREIGN_KEY_CHECKS=ON;
51+
ALTER TABLE t1 ADD b INT;
52+
ALTER TABLE t1 DROP a;
53+
ERROR HY000: Cannot drop index 'a': needed in a foreign key constraint
54+
ALTER TABLE t1 ADD c INT;
55+
DROP TABLE t1, tx;

mysql-test/suite/innodb/t/alter_table.test

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,24 @@ ALTER TABLE t1 ORDER BY a;
3838
DROP TABLE t1;
3939

4040
SET sql_mode=DEFAULT;
41+
42+
--echo #
43+
--echo # MDEV-18775 Server crashes in dict_table_t::instant_column
44+
--echo # upon ADD COLUMN
45+
--echo #
46+
47+
CREATE TABLE tx (pk INT PRIMARY KEY) ENGINE=InnoDB;
48+
CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a), FOREIGN KEY (a) REFERENCES tx (pk)) ENGINE=InnoDB;
49+
50+
SET FOREIGN_KEY_CHECKS=OFF;
51+
52+
--error ER_FK_COLUMN_CANNOT_DROP
53+
ALTER TABLE t1 DROP a;
54+
55+
SET FOREIGN_KEY_CHECKS=ON;
56+
57+
ALTER TABLE t1 ADD b INT;
58+
--error ER_DROP_INDEX_FK
59+
ALTER TABLE t1 DROP a;
60+
ALTER TABLE t1 ADD c INT;
61+
DROP TABLE t1, tx;

storage/innobase/handler/handler0alter.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5142,14 +5142,12 @@ prepare_inplace_alter_table_dict(
51425142
ut_ad(!user_table->drop_aborted);
51435143

51445144
err_exit:
5145-
#ifdef UNIV_DEBUG
51465145
/* Clear the to_be_dropped flag in the data dictionary cache. */
51475146
for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
51485147
DBUG_ASSERT(ctx->drop_index[i]->is_committed());
51495148
DBUG_ASSERT(ctx->drop_index[i]->to_be_dropped);
51505149
ctx->drop_index[i]->to_be_dropped = 0;
51515150
}
5152-
#endif /* UNIV_DEBUG */
51535151

51545152
row_mysql_unlock_data_dictionary(ctx->trx);
51555153

0 commit comments

Comments
 (0)