mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7441,14 +7441,14 @@ innobase_drop_foreign_try(
|
||||
}
|
||||
|
||||
/** Rename a column in the data dictionary tables.
|
||||
@param[in] user_table InnoDB table that was being altered
|
||||
@param[in] trx data dictionary transaction
|
||||
@param[in] table_name Table name in MySQL
|
||||
@param[in] nth_col 0-based index of the column
|
||||
@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] user_table InnoDB table that was being altered
|
||||
@param[in] trx Data dictionary transaction
|
||||
@param[in] table_name Table name in MySQL
|
||||
@param[in] nth_col 0-based index of the column
|
||||
@param[in] from old column name
|
||||
@param[in] to new column name
|
||||
@param[in] new_clustered whether the table has been rebuilt
|
||||
@param[in] evict_fk_cache Evict the fk info from cache
|
||||
@retval true Failure
|
||||
@retval false Success */
|
||||
static MY_ATTRIBUTE((nonnull, warn_unused_result))
|
||||
@@ -7460,7 +7460,8 @@ innobase_rename_column_try(
|
||||
ulint nth_col,
|
||||
const char* from,
|
||||
const char* to,
|
||||
bool new_clustered)
|
||||
bool new_clustered,
|
||||
bool evict_fk_cache)
|
||||
{
|
||||
pars_info_t* info;
|
||||
dberr_t error;
|
||||
@@ -7644,7 +7645,8 @@ rename_foreign:
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
dict_foreign_remove_from_cache);
|
||||
}
|
||||
@@ -7699,7 +7701,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;
|
||||
|
||||
Reference in New Issue
Block a user