MDEV-19630 ALTER TABLE ... ADD COLUMN damages foreign keys

		which are pointed to the table being altered
Problem:
========
	InnoDB failed to change the column name present in foreign key cache
for instant add column. So it leads to column mismatch for the consecutive
rename of column.

Solution:
=========
	Evict the foreign key information from cache and load the foreign
key information again for instant operation.
parent 7df17ca8
...@@ -128,3 +128,29 @@ HANDLER h READ `PRIMARY` PREV WHERE 0; ...@@ -128,3 +128,29 @@ HANDLER h READ `PRIMARY` PREV WHERE 0;
pk f1 f2 f3 f4 f5 f6 f7 f8 filler pk f1 f2 f3 f4 f5 f6 f7 f8 filler
HANDLER h CLOSE; HANDLER h CLOSE;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(f1 int not null, primary key(f1))engine=innodb;
CREATE TABLE t2(f1 INT AUTO_INCREMENT NOT NULL, f2 INT NOT NULL,
status ENUM ('a', 'b', 'c'), INDEX idx1(f2),
PRIMARY KEY(f1),
FOREIGN KEY (f2) REFERENCES t1(f1))ENGINE=InnoDB;
ALTER TABLE t1 CHANGE f1 f1_id INT NOT NULL, ADD f3 VARCHAR(255) DEFAULT NULL;
ALTER TABLE t1 CHANGE f1_id f1 INT NOT NULL;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` int(11) NOT NULL,
`f3` varchar(255) DEFAULT NULL,
PRIMARY KEY (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`f1` int(11) NOT NULL AUTO_INCREMENT,
`f2` int(11) NOT NULL,
`status` enum('a','b','c') DEFAULT NULL,
PRIMARY KEY (`f1`),
KEY `idx1` (`f2`),
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t2 CHANGE status status VARCHAR(20) DEFAULT NULL;
DROP TABLE t2, t1;
...@@ -134,5 +134,23 @@ HANDLER h READ `PRIMARY` PREV WHERE 0; ...@@ -134,5 +134,23 @@ HANDLER h READ `PRIMARY` PREV WHERE 0;
# Cleanup # Cleanup
HANDLER h CLOSE; HANDLER h CLOSE;
DROP TABLE t1; DROP TABLE t1;
# MDEV-19630 ALTER TABLE ... ADD COLUMN damages foreign keys which are pointed
# to the table being altered
CREATE TABLE t1(f1 int not null, primary key(f1))engine=innodb;
CREATE TABLE t2(f1 INT AUTO_INCREMENT NOT NULL, f2 INT NOT NULL,
status ENUM ('a', 'b', 'c'), INDEX idx1(f2),
PRIMARY KEY(f1),
FOREIGN KEY (f2) REFERENCES t1(f1))ENGINE=InnoDB;
ALTER TABLE t1 CHANGE f1 f1_id INT NOT NULL, ADD f3 VARCHAR(255) DEFAULT NULL;
ALTER TABLE t1 CHANGE f1_id f1 INT NOT NULL;
SHOW CREATE TABLE t1;
SHOW CREATE TABLE t2;
ALTER TABLE t2 CHANGE status status VARCHAR(20) DEFAULT NULL;
DROP TABLE t2, t1;
--let $datadir= `select @@datadir` --let $datadir= `select @@datadir`
--remove_file $datadir/test/load.data --remove_file $datadir/test/load.data
...@@ -7441,14 +7441,14 @@ innobase_drop_foreign_try( ...@@ -7441,14 +7441,14 @@ innobase_drop_foreign_try(
} }
/** Rename a column in the data dictionary tables. /** Rename a column in the data dictionary tables.
@param[in] user_table InnoDB table that was being altered @param[in] user_table InnoDB table that was being altered
@param[in] trx data dictionary transaction @param[in] trx Data dictionary transaction
@param[in] table_name Table name in MySQL @param[in] table_name Table name in MySQL
@param[in] nth_col 0-based index of the column @param[in] nth_col 0-based index of the column
@param[in] from old column name @param[in] from old column name
@param[in] to new column name @param[in] to new column name
@param[in] new_clustered whether the table has been rebuilt @param[in] new_clustered whether the table has been rebuilt
@param[in] is_virtual whether it is a virtual column @param[in] evict_fk_cache Evict the fk info from cache
@retval true Failure @retval true Failure
@retval false Success */ @retval false Success */
static MY_ATTRIBUTE((nonnull, warn_unused_result)) static MY_ATTRIBUTE((nonnull, warn_unused_result))
...@@ -7460,7 +7460,8 @@ innobase_rename_column_try( ...@@ -7460,7 +7460,8 @@ innobase_rename_column_try(
ulint nth_col, ulint nth_col,
const char* from, const char* from,
const char* to, const char* to,
bool new_clustered) bool new_clustered,
bool evict_fk_cache)
{ {
pars_info_t* info; pars_info_t* info;
dberr_t error; dberr_t error;
...@@ -7644,7 +7645,8 @@ innobase_rename_column_try( ...@@ -7644,7 +7645,8 @@ innobase_rename_column_try(
} }
} }
if (new_clustered) { /* Reload the foreign key info for instant table too. */
if (new_clustered || evict_fk_cache) {
std::for_each(fk_evict.begin(), fk_evict.end(), std::for_each(fk_evict.begin(), fk_evict.end(),
dict_foreign_remove_from_cache); dict_foreign_remove_from_cache);
} }
...@@ -7699,7 +7701,8 @@ innobase_rename_columns_try( ...@@ -7699,7 +7701,8 @@ innobase_rename_columns_try(
col_n, col_n,
cf->field->field_name.str, cf->field->field_name.str,
cf->field_name.str, cf->field_name.str,
ctx->need_rebuild())) { ctx->need_rebuild(),
ctx->is_instant())) {
return(true); return(true);
} }
goto processed_field; goto processed_field;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment