MDEV-19092 Server crash when renaming the column when

		FOREIGN_KEY_CHECKS is disabled

- Referenced index can be null While renaming the referenced column name.
In that case, rename the referenced column name in dict_foreign_t and
find the equivalent referenced index.
parent d233fd14
...@@ -119,4 +119,14 @@ ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES tx(x); ...@@ -119,4 +119,14 @@ ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES tx(x);
ALTER TABLE t1 DROP KEY idx; ALTER TABLE t1 DROP KEY idx;
ALTER TABLE t1 CHANGE a c INT; ALTER TABLE t1 CHANGE a c INT;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, KEY idx(f1)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t1 (f1);
ALTER TABLE t1 ADD COLUMN f INT;
SET FOREIGN_KEY_CHECKS= OFF;
ALTER TABLE t1 DROP KEY idx;
ALTER TABLE t1 ADD KEY idx (f1);
SET FOREIGN_KEY_CHECKS= ON;
ALTER TABLE t1 DROP f3;
ALTER TABLE t1 CHANGE f f3 INT;
DROP TABLE t1;
SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS=1;
...@@ -144,4 +144,17 @@ ALTER TABLE t1 DROP KEY idx; ...@@ -144,4 +144,17 @@ ALTER TABLE t1 DROP KEY idx;
ALTER TABLE t1 CHANGE a c INT; ALTER TABLE t1 CHANGE a c INT;
# Cleanup # Cleanup
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, KEY idx(f1)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FOREIGN KEY (f2) REFERENCES t1 (f1);
ALTER TABLE t1 ADD COLUMN f INT;
SET FOREIGN_KEY_CHECKS= OFF;
ALTER TABLE t1 DROP KEY idx;
ALTER TABLE t1 ADD KEY idx (f1);
SET FOREIGN_KEY_CHECKS= ON;
ALTER TABLE t1 DROP f3;
ALTER TABLE t1 CHANGE f f3 INT;
# Cleanup
DROP TABLE t1;
SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS=1;
...@@ -415,17 +415,15 @@ dict_mem_table_col_rename_low( ...@@ -415,17 +415,15 @@ dict_mem_table_col_rename_low(
} }
} }
dict_index_t* new_index = dict_foreign_find_index( /* New index can be null if InnoDB already dropped
the foreign index when FOREIGN_KEY_CHECKS is
disabled */
foreign->foreign_index = dict_foreign_find_index(
foreign->foreign_table, NULL, foreign->foreign_table, NULL,
foreign->foreign_col_names, foreign->foreign_col_names,
foreign->n_fields, NULL, true, false, foreign->n_fields, NULL, true, false,
NULL, NULL, NULL); NULL, NULL, NULL);
/* New index can be null if InnoDB already dropped
the foreign index when FOREIGN_KEY_CHECKS is
disabled */
foreign->foreign_index = new_index;
} else { } else {
for (unsigned f = 0; f < foreign->n_fields; f++) { for (unsigned f = 0; f < foreign->n_fields; f++) {
...@@ -447,7 +445,41 @@ dict_mem_table_col_rename_low( ...@@ -447,7 +445,41 @@ dict_mem_table_col_rename_low(
foreign = *it; foreign = *it;
ut_ad(foreign->referenced_index != NULL); if (!foreign->referenced_index) {
/* Referenced index could have been dropped
when foreign_key_checks is disabled. In that case,
rename the corresponding referenced_col_names and
find the equivalent referenced index also */
for (unsigned f = 0; f < foreign->n_fields; f++) {
const char*& rc =
foreign->referenced_col_names[f];
if (strcmp(rc, from)) {
continue;
}
if (to_len <= strlen(rc)) {
memcpy(const_cast<char*>(rc), to,
to_len + 1);
} else {
rc = static_cast<char*>(
mem_heap_dup(
foreign->heap,
to, to_len + 1));
}
}
/* New index can be null if InnoDB already dropped
the referenced index when FOREIGN_KEY_CHECKS is
disabled */
foreign->referenced_index = dict_foreign_find_index(
foreign->referenced_table, NULL,
foreign->referenced_col_names,
foreign->n_fields, NULL, true, false,
NULL, NULL, NULL);
return;
}
for (unsigned f = 0; f < foreign->n_fields; f++) { for (unsigned f = 0; f < foreign->n_fields; f++) {
/* foreign->referenced_col_names[] need to be /* foreign->referenced_col_names[] need to be
......
...@@ -416,17 +416,15 @@ dict_mem_table_col_rename_low( ...@@ -416,17 +416,15 @@ dict_mem_table_col_rename_low(
} }
} }
dict_index_t* new_index = dict_foreign_find_index( /* New index can be null if XtraDB already dropped
the foreign index when FOREIGN_KEY_CHECKS is
disabled */
foreign->foreign_index = dict_foreign_find_index(
foreign->foreign_table, NULL, foreign->foreign_table, NULL,
foreign->foreign_col_names, foreign->foreign_col_names,
foreign->n_fields, NULL, true, false, foreign->n_fields, NULL, true, false,
NULL, NULL, NULL); NULL, NULL, NULL);
/* New index can be null if XtraDB already dropped
the foreign index when FOREIGN_KEY_CHECKS is
disabled */
foreign->foreign_index = new_index;
} else { } else {
for (unsigned f = 0; f < foreign->n_fields; f++) { for (unsigned f = 0; f < foreign->n_fields; f++) {
...@@ -448,7 +446,41 @@ dict_mem_table_col_rename_low( ...@@ -448,7 +446,41 @@ dict_mem_table_col_rename_low(
foreign = *it; foreign = *it;
ut_ad(foreign->referenced_index != NULL); if (!foreign->referenced_index) {
/* Referenced index could have been dropped
when foreign_key_checks is disabled. In that case,
rename the corresponding referenced_col_names and
find the equivalent referenced index also */
for (unsigned f = 0; f < foreign->n_fields; f++) {
const char*& rc =
foreign->referenced_col_names[f];
if (strcmp(rc, from)) {
continue;
}
if (to_len <= strlen(rc)) {
memcpy(const_cast<char*>(rc), to,
to_len + 1);
} else {
rc = static_cast<char*>(
mem_heap_dup(
foreign->heap,
to, to_len + 1));
}
}
/* New index can be null if InnoDB already dropped
the referenced index when FOREIGN_KEY_CHECKS is
disabled */
foreign->referenced_index = dict_foreign_find_index(
foreign->referenced_table, NULL,
foreign->referenced_col_names,
foreign->n_fields, NULL, true, false,
NULL, NULL, NULL);
return;
}
for (unsigned f = 0; f < foreign->n_fields; f++) { for (unsigned f = 0; f < foreign->n_fields; f++) {
/* foreign->referenced_col_names[] need to be /* foreign->referenced_col_names[] need to be
......
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