summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-07-09 17:03:02 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-07-09 17:03:02 +0530
commit0e4b61369f1a787bd24bdb0250aa5062a028ff11 (patch)
tree336d4b0c0016cbdc5c6836338fd6537f5a84496d
parent4d887ee4e61355a5f3fbfdf5abab5de2909da8bf (diff)
downloadmariadb-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.result26
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_bugs.test18
-rw-r--r--storage/innobase/handler/handler0alter.cc12
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;