diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-07-09 17:03:02 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-07-09 17:03:02 +0530 |
commit | 0e4b61369f1a787bd24bdb0250aa5062a028ff11 (patch) | |
tree | 336d4b0c0016cbdc5c6836338fd6537f5a84496d | |
parent | 4d887ee4e61355a5f3fbfdf5abab5de2909da8bf (diff) | |
download | mariadb-git-bb-10.3-MDEV-19974.tar.gz |
MDEV-19630 ALTER TABLE ... ADD COLUMN damages foreign keysbb-10.3-MDEV-19974
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.
-rw-r--r-- | mysql-test/suite/innodb/r/instant_alter_bugs.result | 26 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/instant_alter_bugs.test | 18 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 12 |
3 files changed, 52 insertions, 4 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index 14d88c64de8..080395b0120 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -128,3 +128,29 @@ HANDLER h READ `PRIMARY` PREV WHERE 0; pk f1 f2 f3 f4 f5 f6 f7 f8 filler HANDLER h CLOSE; 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; diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 9cc0037703b..bab102ebd7f 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -134,5 +134,23 @@ HANDLER h READ `PRIMARY` PREV WHERE 0; # Cleanup HANDLER h CLOSE; 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` --remove_file $datadir/test/load.data diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 571ec821999..bde0166db94 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7448,7 +7448,8 @@ innobase_drop_foreign_try( @param[in] from old column name @param[in] to new column name @param[in] new_clustered whether the table has been rebuilt -@param[in] is_virtual whether it is a virtual column +@param[in] instant_table In case of instant table, reload the + foreign key information again. @retval true Failure @retval false Success */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -7460,7 +7461,8 @@ innobase_rename_column_try( ulint nth_col, const char* from, const char* to, - bool new_clustered) + bool new_clustered, + bool instant_table) { pars_info_t* info; dberr_t error; @@ -7644,7 +7646,8 @@ rename_foreign: } } - if (new_clustered) { + /* Reload the foreign key info for instant table too. */ + if (new_clustered || instant_table) { std::for_each(fk_evict.begin(), fk_evict.end(), dict_foreign_remove_from_cache); } @@ -7699,7 +7702,8 @@ innobase_rename_columns_try( col_n, cf->field->field_name.str, cf->field_name.str, - ctx->need_rebuild())) { + ctx->need_rebuild(), + ctx->is_instant())) { return(true); } goto processed_field; |