diff --git a/mysql-test/suite/innodb/r/fk_col_alter.result b/mysql-test/suite/innodb/r/fk_col_alter.result new file mode 100644 index 00000000000..edd90e05ecd --- /dev/null +++ b/mysql-test/suite/innodb/r/fk_col_alter.result @@ -0,0 +1,77 @@ +# +# MDEV-31086 MODIFY COLUMN can break FK constraints, and +# lead to unrestorable dumps +# +CREATE TABLE t1( +id SERIAL, +msg VARCHAR(100) CHARACTER SET utf8mb3, +KEY(msg))ENGINE=InnoDB; +CREATE TABLE t2( +id SERIAL, +msg varchar(100) CHARACTER SET utf8mb4, +CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg))ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +CREATE TABLE t2( +id SERIAL, +msg varchar(100) CHARACTER SET utf8mb3, +msg_1 varchar(100) CHARACTER SET utf8mb3, +INDEX (msg_1), +INDEX (msg), +CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg) +ON DELETE CASCADE)ENGINE=InnoDB; +SET FOREIGN_KEY_CHECKS=1; +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=INPLACE; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(400) character set utf8mb3, ALGORITHM=INPLACE; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' +SET FOREIGN_KEY_CHECKS=1; +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +SET FOREIGN_KEY_CHECKS=1; +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; +ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Adding foreign keys needs foreign_key_checks=OFF. Try ALGORITHM=COPY +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; +ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(200) CHARACTER SET utf8mb3, ALGORITHM=INPLACE; +ERROR HY000: Cannot change column 'msg_1': used in a foreign key constraint 'test/t2_ibfk_0' +SET FOREIGN_KEY_CHECKS=1; +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=INPLACE; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' of table 'test/t2' +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' +ALTER TABLE t1 MODIFY msg VARCHAR(400) CHARSET utf8mb3, ALGORITHM=INPLACE; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'test/fk_t1' of table 'test/t2' +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +ERROR HY000: Cannot change column 'msg': used in a foreign key constraint 'fk_t1' of table 'test.t2' +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 DROP FOREIGN KEY fk_t1, MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY (msg) REFERENCES t1(msg), aLGORITHM=INPLACE; +SET FOREIGN_KEY_CHECKS=1; +DROP TABLE t2, t1; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 802019d493e..68a54344519 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -246,8 +246,11 @@ CREATE TABLE t1 (a INT, UNIQUE(a), KEY(a)) ENGINE=InnoDB; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a); SET SESSION FOREIGN_KEY_CHECKS = OFF; ALTER TABLE t1 CHANGE COLUMN a a TIME NOT NULL; +ERROR HY000: Cannot change column 'a': used in a foreign key constraint 't1_ibfk_1' of table 'test.t1' ALTER TABLE t1 ADD pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY; ALTER TABLE t1 CHANGE COLUMN a b TIME; +ERROR 0A000: ALGORITHM=COPY is not supported. Reason: Columns participating in a foreign key are renamed. Try ALGORITHM=INPLACE +ALTER TABLE t1 CHANGE COLUMN a b TIME, DROP FOREIGN KEY t1_ibfk_1; SET SESSION FOREIGN_KEY_CHECKS = ON; DROP TABLE t1; # diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 23f9ac89495..5e0f231d419 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -2544,12 +2544,14 @@ set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; create table t1(a varchar(10) primary key) engine = innodb; alter table t1 modify column a int; +ERROR HY000: Cannot change column 'a': used in a foreign key constraint 't2_ibfk_1' of table 'test.t2' set foreign_key_checks=1; drop table t2,t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; alter table t1 convert to character set utf8; +ERROR HY000: Cannot change column 'a': used in a foreign key constraint 't2_ibfk_1' of table 'test.t2' set foreign_key_checks=1; drop table t2,t1; call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition."); diff --git a/mysql-test/suite/innodb/t/fk_col_alter.test b/mysql-test/suite/innodb/t/fk_col_alter.test new file mode 100644 index 00000000000..d8b9afc92ad --- /dev/null +++ b/mysql-test/suite/innodb/t/fk_col_alter.test @@ -0,0 +1,106 @@ +--source include/have_innodb.inc +--echo # +--echo # MDEV-31086 MODIFY COLUMN can break FK constraints, and +--echo # lead to unrestorable dumps +--echo # +CREATE TABLE t1( + id SERIAL, + msg VARCHAR(100) CHARACTER SET utf8mb3, + KEY(msg))ENGINE=InnoDB; + +--error ER_CANT_CREATE_TABLE +CREATE TABLE t2( +id SERIAL, +msg varchar(100) CHARACTER SET utf8mb4, +CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg))ENGINE=InnoDB; + +CREATE TABLE t2( +id SERIAL, +msg varchar(100) CHARACTER SET utf8mb3, +msg_1 varchar(100) CHARACTER SET utf8mb3, +INDEX (msg_1), +INDEX (msg), +CONSTRAINT fk_t1 FOREIGN KEY (msg) REFERENCES t1 (msg) +ON DELETE CASCADE)ENGINE=InnoDB; + +# Changing column used in FK constraint +SET FOREIGN_KEY_CHECKS=1; +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=INPLACE; + +SET FOREIGN_KEY_CHECKS=0; +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(200) character set utf8mb3, ALGORITHM=COPY; +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(400) character set utf8mb3, ALGORITHM=INPLACE; + +# Changing column charset used in FK constraint +SET FOREIGN_KEY_CHECKS=1; +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; + +SET FOREIGN_KEY_CHECKS=0; +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=COPY; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t2 MODIFY COLUMN msg VARCHAR(100) CHARACTER SET utf8mb4,ALGORITHM=INPLACE; + +# Modify the column in the newly added foreign constraint +SET FOREIGN_KEY_CHECKS=1; +--error ER_CANT_CREATE_TABLE +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; + + +SET FOREIGN_KEY_CHECKS=0; +--error ER_CANT_CREATE_TABLE +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=COPY; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(100) CHARACTER SET utf8mb4, ALGORITHM=INPLACE; + +--error ER_FK_COLUMN_CANNOT_CHANGE +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY(msg_1) REFERENCES t1(msg),MODIFY COLUMN msg_1 VARCHAR(200) CHARACTER SET utf8mb3, ALGORITHM=INPLACE; + +# Change referenced table column +SET FOREIGN_KEY_CHECKS=1; +# Change referenced column length +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=INPLACE; +# Change referenced column character set +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; + +SET FOREIGN_KEY_CHECKS=0; +# Change referenced column length +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb3, ALGORITHM=COPY; +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD +ALTER TABLE t1 MODIFY msg VARCHAR(400) CHARSET utf8mb3, ALGORITHM=INPLACE; + +# Change referenced column character set +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=INPLACE; + +# Correct way to change character set in foreign key constraint +SET FOREIGN_KEY_CHECKS=0; +ALTER TABLE t2 DROP FOREIGN KEY fk_t1, MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +ALTER TABLE t1 MODIFY msg VARCHAR(200) CHARSET utf8mb4, ALGORITHM=COPY; +ALTER TABLE t2 ADD CONSTRAINT FOREIGN KEY (msg) REFERENCES t1(msg), aLGORITHM=INPLACE; +SET FOREIGN_KEY_CHECKS=1; + +DROP TABLE t2, t1; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 4f3f07757d5..4caa4cc2431 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -239,9 +239,12 @@ DROP TABLE t3,t1; CREATE TABLE t1 (a INT, UNIQUE(a), KEY(a)) ENGINE=InnoDB; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a); SET SESSION FOREIGN_KEY_CHECKS = OFF; +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD ALTER TABLE t1 CHANGE COLUMN a a TIME NOT NULL; ALTER TABLE t1 ADD pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON ALTER TABLE t1 CHANGE COLUMN a b TIME; +ALTER TABLE t1 CHANGE COLUMN a b TIME, DROP FOREIGN KEY t1_ibfk_1; SET SESSION FOREIGN_KEY_CHECKS = ON; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index ba5126e4757..b50fd995e83 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1626,6 +1626,7 @@ drop table t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb; create table t1(a varchar(10) primary key) engine = innodb; +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD alter table t1 modify column a int; set foreign_key_checks=1; drop table t2,t1; @@ -1635,6 +1636,7 @@ drop table t2,t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +--error ER_FK_COLUMN_CANNOT_CHANGE_CHILD alter table t1 convert to character set utf8; set foreign_key_checks=1; drop table t2,t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b0f7d848068..100436ae1ef 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9143,17 +9143,12 @@ fk_check_column_changes(THD *thd, Alter_info *alter_info, ((new_field->flags & NOT_NULL_FLAG) && !(old_field->flags & NOT_NULL_FLAG))) { - if (!(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)) - { - /* - Column in a FK has changed significantly. Unless - foreign_key_checks are off we prohibit this since this - means values in this column might be changed by ALTER - and thus referential integrity might be broken, - */ - *bad_column_name= column->str; - return FK_COLUMN_DATA_CHANGE; - } + /* + Column in a FK has changed significantly and it + may break referential intergrity. + */ + *bad_column_name= column->str; + return FK_COLUMN_DATA_CHANGE; } } else diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 17fe6014fea..9ec025d6141 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7662,6 +7662,71 @@ static bool alter_templ_needs_rebuild(const TABLE* altered_table, const Alter_inplace_info* ha_alter_info, const dict_table_t* table); +/** Check whether the column is present in table foreign key +relations. +@param table table which has foreign key relation +@param col column to be checked +@param col_name column name to be display during error +@param drop_fk Drop foreign key constraint +@param n_drop_fk number of drop foreign keys +@param add_fk Newly added foreign key constraint +@param n_add_fk number of newly added foreign constraint */ +static +bool check_col_is_in_fk_indexes( + const dict_table_t *table, const dict_col_t *col, + const char* col_name, + span drop_fk, + span add_fk) +{ + char *fk_id= nullptr; + + for (dict_foreign_set::iterator it= table->foreign_set.begin(); + it!= table->foreign_set.end();) + { + if (std::find(drop_fk.begin(), drop_fk.end(), (*it)) + != drop_fk.end()) + goto next_item; + for (ulint i= 0; i < (*it)->n_fields; i++) + if ((*it)->foreign_index->fields[i].col == col) + { + fk_id= (*it)->id; + goto err_exit; + } +next_item: + it++; + } + + for (const auto &a : add_fk) + { + for (ulint i= 0; i < a->n_fields; i++) + { + if (a->foreign_index->fields[i].col == col) + { + fk_id= a->id; + goto err_exit; + } + } + } + + for (const auto &f : table->referenced_set) + { + for (ulint i= 0; i < f->n_fields; i++) + { + if (f->referenced_index->fields[i].col == col) + { + my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), + col_name, f->id, f->foreign_table_name); + return true; + } + } + } + return false; +err_exit: + my_error(ER_FK_COLUMN_CANNOT_CHANGE, MYF(0), col_name, + fk_id ? fk_id : + (std::string(table->name.m_name) + "_ibfk_0").c_str()); + return true; +} /** Allows InnoDB to update internal structures with concurrent writes blocked (provided that check_if_supported_inplace_alter() @@ -7687,7 +7752,7 @@ ha_innobase::prepare_inplace_alter_table( dict_foreign_t**drop_fk; /*!< Foreign key constraints to drop */ ulint n_drop_fk; /*!< Number of foreign keys to drop */ dict_foreign_t**add_fk = NULL; /*!< Foreign key constraints to drop */ - ulint n_add_fk; /*!< Number of foreign keys to drop */ + ulint n_add_fk= 0; /*!< Number of foreign keys to drop */ dict_table_t* indexed_table; /*!< Table where indexes are created */ mem_heap_t* heap; const char** col_names; @@ -8204,8 +8269,6 @@ check_if_can_drop_indexes: } } - n_add_fk = 0; - if (ha_alter_info->handler_flags & ALTER_ADD_FOREIGN_KEY) { ut_ad(!m_prebuilt->trx->check_foreigns); @@ -8239,6 +8302,12 @@ err_exit: m_prebuilt->trx); } + for (uint i = 0; i < n_add_fk; i++) { + if (add_fk[i]) { + dict_foreign_free(add_fk[i]); + } + } + if (heap) { mem_heap_free(heap); } @@ -8257,6 +8326,33 @@ err_exit: } } + /** Alter shouldn't support if the foreign and referenced + index columns are modified */ + if (ha_alter_info->handler_flags + & ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) { + List_iterator it( + ha_alter_info->alter_info->create_list); + for (uint i = 0; i < table->s->fields; i++) { + Field* field = table->field[i]; + Create_field *f= it++; + if (!f->field || field->is_equal(*f)) + continue; + + const char* col_name= field->field_name.str; + dict_col_t *col= dict_table_get_nth_col( + m_prebuilt->table, i); + if (check_col_is_in_fk_indexes( + m_prebuilt->table, col, col_name, + span( + const_cast( + drop_fk), n_drop_fk), + span( + const_cast( + add_fk), n_add_fk))) + goto err_exit; + } + } + if (ha_alter_info->handler_flags & ALTER_RENAME_INDEX) { for (const Alter_inplace_info::Rename_key_pair& pair : ha_alter_info->rename_keys) {