summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2023-01-18 16:52:10 +0300
committerAleksey Midenkov <midenok@gmail.com>2023-01-26 17:15:20 +0300
commit7aadd088fda40b8fefc0def9a2494503f8bc31f7 (patch)
tree4843535099b925510d1187589de40f7afe838ed8
parent2d5758af5a8ab43d200026efc510df26e4b58266 (diff)
downloadmariadb-git-7aadd088fda40b8fefc0def9a2494503f8bc31f7.tar.gz
MDEV-28933 CREATE OR REPLACE fails to recreate same constraint name
Use temporary constraint names for temporary tables. The constraints are not added to cache (skipped in dict_table_rename_in_cache()). The scheme for temporary constraint names is as follows: for old table: db_name/\xFFconstraint_name for new table: db_name/\xFF\xFFconstraint_name normalize_table_name_c_low(): wrong comparison "less than FN_REFLEN - 1". Somewhere array of FN_REFLEN includes the trailing 0, somewhere array of FN_REFLEN + 1 includes trailing 0, but nowhere array of FN_REFLEN - 1 must include trailing 0.
-rw-r--r--mysql-test/main/create_or_replace.result28
-rw-r--r--mysql-test/main/create_or_replace.test22
-rw-r--r--mysql-test/suite/innodb/r/foreign_key_not_windows.result43
-rw-r--r--mysql-test/suite/innodb/t/foreign_key_not_windows.test47
-rw-r--r--mysql-test/suite/versioning/r/foreign.result17
-rw-r--r--mysql-test/suite/versioning/t/foreign.test6
-rw-r--r--storage/innobase/dict/dict0dict.cc14
-rw-r--r--storage/innobase/dict/dict0load.cc4
-rw-r--r--storage/innobase/handler/ha_innodb.cc21
-rw-r--r--storage/innobase/include/sql_funcs.h35
-rw-r--r--storage/innobase/row/row0mysql.cc8
11 files changed, 222 insertions, 23 deletions
diff --git a/mysql-test/main/create_or_replace.result b/mysql-test/main/create_or_replace.result
index 5eca9239de5..cb66af9480a 100644
--- a/mysql-test/main/create_or_replace.result
+++ b/mysql-test/main/create_or_replace.result
@@ -874,3 +874,31 @@ select * from t2;
a
unlock tables;
drop tables t2, t1;
+#
+# MDEV-28933 CREATE OR REPLACE fails to recreate same constraint name
+#
+use test;
+create table t (a int primary key) engine=innodb;
+create or replace table u (
+a int primary key,
+constraint c foreign key d (a) references t (a)) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+test/c test/u test/t 1 0
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
+test/c a a 0
+create or replace table u (
+a int primary key,
+constraint c foreign key d (a) references t (a)) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+test/c test/u test/t 1 0
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
+test/c a a 0
+drop tables u, t;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
diff --git a/mysql-test/main/create_or_replace.test b/mysql-test/main/create_or_replace.test
index b0593e2d1cb..1df8f3aa066 100644
--- a/mysql-test/main/create_or_replace.test
+++ b/mysql-test/main/create_or_replace.test
@@ -675,3 +675,25 @@ unlock tables;
drop tables t2, t1;
--enable_service_connection
+
+--echo #
+--echo # MDEV-28933 CREATE OR REPLACE fails to recreate same constraint name
+--echo #
+use test;
+create table t (a int primary key) engine=innodb;
+create or replace table u (
+ a int primary key,
+ constraint c foreign key d (a) references t (a)) engine=innodb;
+
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
+
+create or replace table u (
+ a int primary key,
+ constraint c foreign key d (a) references t (a)) engine=innodb;
+
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
+drop tables u, t;
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
diff --git a/mysql-test/suite/innodb/r/foreign_key_not_windows.result b/mysql-test/suite/innodb/r/foreign_key_not_windows.result
index aaff06f8d68..02b2e3c29af 100644
--- a/mysql-test/suite/innodb/r/foreign_key_not_windows.result
+++ b/mysql-test/suite/innodb/r/foreign_key_not_windows.result
@@ -6,11 +6,20 @@ CREATE DATABASE `d255`;
CREATE TABLE `d255`.`d255`
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
ERROR HY000: Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@
+CREATE OR REPLACE TABLE `d255`.`d255`
+(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+ERROR HY000: Long database name and identifier for object resulted in path length exceeding 511 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@
CREATE TABLE `d255`.`_##################################################`
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
ERROR HY000: Long database name and identifier for object resulted in path length exceeding 512 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/_@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023
+CREATE OR REPLACE TABLE `d255`.`_##################################################`
+(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+ERROR HY000: Long database name and identifier for object resulted in path length exceeding 511 characters. Path: './@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023/_@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023@0023
CREATE TABLE `d255`.`##################################################`
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+CREATE OR REPLACE TABLE `d255`.`d245`
+(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+DROP TABLE `d255`.`d245`;
#
# MDEV-29258 Failing assertion for name length on RENAME TABLE
#
@@ -29,3 +38,37 @@ RENAME TABLE `d255`.u TO u;
DROP TABLE u;
DROP DATABASE `d255`;
# End of 10.3 tests
+#
+# MDEV-28933 CREATE OR REPLACE fails to recreate same constraint name
+#
+set names utf8;
+create database `❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎`;
+use `❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎`;
+create table t (a int primary key) engine=innodb;
+create table u (
+a int primary key,
+constraint `❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎` foreign key d (a) references t (a)) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 @274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 @274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 1 0
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
+@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 a a 0
+create or replace table u (
+a int primary key,
+constraint `❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎` foreign key d (a) references t (a)) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 @274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 @274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 1 0
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
+@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@274e@27 a a 0
+show create table u;
+Table Create Table
+u CREATE TABLE `u` (
+ `a` int(11) NOT NULL,
+ PRIMARY KEY (`a`),
+ CONSTRAINT `❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎` FOREIGN KEY (`a`) REFERENCES `t` (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
+use test;
+drop database `❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎`;
diff --git a/mysql-test/suite/innodb/t/foreign_key_not_windows.test b/mysql-test/suite/innodb/t/foreign_key_not_windows.test
index e5f42a0ddab..67e8935c660 100644
--- a/mysql-test/suite/innodb/t/foreign_key_not_windows.test
+++ b/mysql-test/suite/innodb/t/foreign_key_not_windows.test
@@ -25,20 +25,43 @@ CREATE TABLE t (a INT PRIMARY KEY) ENGINE=InnoDB;
# corresponding to the 51 characters below: 5*51=255.
let $d255=###################################################;
let $d250=##################################################;
+let $d245=#####################;
+# FIXME: MDEV-29258
+# let $d245=#################################################;
--replace_result $d255 d255
eval CREATE DATABASE `$d255`;
+
--replace_result $d255 d255
--error ER_IDENT_CAUSES_TOO_LONG_PATH
eval CREATE TABLE `$d255`.`$d255`
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+
+--replace_result $d255 d255
+--error ER_IDENT_CAUSES_TOO_LONG_PATH
+eval CREATE OR REPLACE TABLE `$d255`.`$d255`
+(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+
--replace_result $d255 d255
--error ER_IDENT_CAUSES_TOO_LONG_PATH
eval CREATE TABLE `$d255`.`_$d250`
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+
+--replace_result $d255 d255
+--error ER_IDENT_CAUSES_TOO_LONG_PATH
+eval CREATE OR REPLACE TABLE `$d255`.`_$d250`
+(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+
--replace_result $d255 d255
eval CREATE TABLE `$d255`.`$d250`
(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+--replace_result $d255 d255 $d245 d245
+eval CREATE OR REPLACE TABLE `$d255`.`$d245`
+(a INT PRIMARY KEY, FOREIGN KEY(a) REFERENCES test.t(a)) ENGINE=InnoDB;
+
+--replace_result $d255 d255 $d245 d245
+eval DROP TABLE `$d255`.`$d245`;
+
--echo #
--echo # MDEV-29258 Failing assertion for name length on RENAME TABLE
--echo #
@@ -53,7 +76,6 @@ eval DROP TABLE `$d255`.`$d250`;
eval RENAME TABLE `$d255`.`$d245` TO `$d255`.`$d250`;
--replace_result $d250 d250 $d255 d255
eval RENAME TABLE `$d255`.`$d250` TO a;
---replace_result $d255 d255
DROP TABLE a,t;
--echo #
@@ -75,3 +97,26 @@ DROP TABLE u;
eval DROP DATABASE `$d255`;
--echo # End of 10.3 tests
+
+--echo #
+--echo # MDEV-28933 CREATE OR REPLACE fails to recreate same constraint name
+--echo #
+set names utf8;
+let $d= `select repeat('❎', 45)`;
+let $t= `select repeat('❎', 64)`;
+eval create database `$d`;
+eval use `$d`;
+create table t (a int primary key) engine=innodb;
+eval create table u (
+ a int primary key,
+ constraint `$t` foreign key d (a) references t (a)) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
+eval create or replace table u (
+ a int primary key,
+ constraint `$t` foreign key d (a) references t (a)) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
+show create table u;
+use test;
+eval drop database `$d`;
diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result
index b17deba1c1e..45824b3800e 100644
--- a/mysql-test/suite/versioning/r/foreign.result
+++ b/mysql-test/suite/versioning/r/foreign.result
@@ -263,6 +263,13 @@ constraint `fk_child_parent`
on delete cascade
on update cascade
) engine = innodb with system versioning;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+test/fk_child_parent test/child test/parent 2 5
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
+test/fk_child_parent parent_id id 0
+test/fk_child_parent parent_value value 1
create or replace table subchild (
id int not null auto_increment primary key,
parent_id smallint unsigned not null,
@@ -272,6 +279,16 @@ constraint `fk_subchild_child_parent`
on delete cascade
on update cascade
) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+ID FOR_NAME REF_NAME N_COLS TYPE
+test/fk_child_parent test/child test/parent 2 5
+test/fk_subchild_child_parent test/subchild test/child 2 5
+select * from information_schema.innodb_sys_foreign_cols;
+ID FOR_COL_NAME REF_COL_NAME POS
+test/fk_child_parent parent_id id 0
+test/fk_child_parent parent_value value 1
+test/fk_subchild_child_parent parent_id parent_id 0
+test/fk_subchild_child_parent parent_value parent_value 1
insert into parent (value) values (23);
select id, value from parent into @id, @value;
Warnings:
diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test
index c94cff540c6..c1c9523b75f 100644
--- a/mysql-test/suite/versioning/t/foreign.test
+++ b/mysql-test/suite/versioning/t/foreign.test
@@ -303,6 +303,9 @@ eval create or replace table child (
on update cascade
) engine = innodb with system versioning;
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
+
create or replace table subchild (
id int not null auto_increment primary key,
parent_id smallint unsigned not null,
@@ -313,6 +316,9 @@ create or replace table subchild (
on update cascade
) engine=innodb;
+select * from information_schema.innodb_sys_foreign;
+select * from information_schema.innodb_sys_foreign_cols;
+
insert into parent (value) values (23);
--enable_prepare_warnings
select id, value from parent into @id, @value;
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index d652324e909..e630f752d23 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1652,7 +1652,9 @@ dict_table_rename_in_cache(
table->name.m_name);
dict_mem_foreign_table_name_lookup_set(foreign, FALSE);
}
- if (strchr(foreign->id, '/')) {
+
+ const bool tmp_id = (strchr(foreign->id, '\xFF') != NULL);
+ if (!tmp_id && strchr(foreign->id, '/')) {
/* This is a >= 4.0.18 format id */
ulint db_len;
@@ -1796,10 +1798,14 @@ dict_table_rename_in_cache(
}
table->foreign_set.erase(it);
- fk_set.insert(foreign);
- if (foreign->referenced_table) {
- foreign->referenced_table->referenced_set.insert(foreign);
+ if (!tmp_id) {
+ fk_set.insert(foreign);
+
+ if (foreign->referenced_table) {
+ foreign->referenced_table
+ ->referenced_set.insert(foreign);
+ }
}
}
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index cb81e4008df..f57f278a32f 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -3144,8 +3144,8 @@ loop:
rec, DICT_FLD__SYS_FOREIGN_FOR_NAME__ID, &len);
/* Copy the string because the page may be modified or evicted
- after mtr.commit() below. */
- char fk_id[MAX_TABLE_NAME_LEN + NAME_LEN];
+ after mtr.commit() below (-2 is for \xFF\xFF in tmp constraints). */
+ char fk_id[MAX_TABLE_NAME_LEN + NAME_LEN - 2];
err = DB_SUCCESS;
if (UNIV_LIKELY(len < sizeof fk_id)) {
memcpy(fk_id, field, len);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c9ab5059e15..7470d18d048 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -5176,7 +5176,7 @@ normalize_table_name_c_low(
db_ptr = ptr + 1;
norm_len = db_len + name_len + sizeof "/";
- ut_a(norm_len < FN_REFLEN - 1);
+ ut_a(norm_len < FN_REFLEN);
memcpy(norm_name, db_ptr, db_len);
@@ -12342,6 +12342,7 @@ create_table_info_t::create_foreign_keys()
if (fk->constraint_name.str) {
ulint db_len;
+ const bool tmp= m_create_info->is_atomic_replace();
/* Catenate 'databasename/' to the constraint name
specified by the user: we conceive the constraint as
@@ -12351,13 +12352,17 @@ create_table_info_t::create_foreign_keys()
db_len = dict_get_db_name_len(table->name.m_name);
foreign->id = static_cast<char*>(mem_heap_alloc(
- foreign->heap,
- db_len + fk->constraint_name.length + 2));
-
- memcpy(foreign->id, table->name.m_name, db_len);
- foreign->id[db_len] = '/';
- strcpy(foreign->id + db_len + 1,
- fk->constraint_name.str);
+ foreign->heap, (tmp ? 3 : 2)
+ + db_len + fk->constraint_name.length));
+
+ char *pos = foreign->id;
+ memcpy(pos, table->name.m_name, db_len);
+ pos += db_len;
+ *(pos++) = '/';
+ if (tmp) {
+ *(pos++) = '\xFF';
+ }
+ strcpy(pos, fk->constraint_name.str);
}
if (foreign->id == NULL) {
diff --git a/storage/innobase/include/sql_funcs.h b/storage/innobase/include/sql_funcs.h
index 307756196b1..1506a2a5a48 100644
--- a/storage/innobase/include/sql_funcs.h
+++ b/storage/innobase/include/sql_funcs.h
@@ -32,12 +32,15 @@ R"===(PROCEDURE RENAME_CONSTRAINT_IDS () IS
gen_constr_prefix CHAR;
new_db_name CHAR;
foreign_id CHAR;
+ foreign_id2 CHAR;
+ constr_name CHAR;
new_foreign_id CHAR;
old_db_name_len INT;
- old_t_name_len INT;
new_db_name_len INT;
id_len INT;
offset INT;
+ offset2 INT;
+ constr_name_len INT;
found INT;
BEGIN
found := 1;
@@ -45,7 +48,6 @@ R"===(PROCEDURE RENAME_CONSTRAINT_IDS () IS
new_db_name_len := INSTR(:new_table_name, '/') - 1;
new_db_name := SUBSTR(:new_table_name, 0,
new_db_name_len);
- old_t_name_len := LENGTH(:old_table_name);
gen_constr_prefix := CONCAT(:old_table_name_utf8,
'_ibfk_');
WHILE found = 1 LOOP
@@ -62,6 +64,18 @@ R"===(PROCEDURE RENAME_CONSTRAINT_IDS () IS
SET FOR_NAME = :new_table_name
WHERE ID = foreign_id;
id_len := LENGTH(foreign_id);
+ foreign_id2 := foreign_id;
+ offset := INSTR(foreign_id, ')===" "\xFF" R"===(');
+ IF (SUBSTR(foreign_id, offset, 1) = ')===" "\xFF" R"===(') THEN
+ offset2 := offset + 1;
+ ELSE
+ offset2 := offset;
+ END IF;
+ IF (:old_is_tmp > 0 AND offset > 0) THEN
+ foreign_id := CONCAT(SUBSTR(foreign_id2, 0, offset - 1),
+ SUBSTR(foreign_id2, offset2, id_len - offset2));
+ id_len := id_len - 1;
+ END IF;
IF (INSTR(foreign_id, '/') > 0) THEN
IF (INSTR(foreign_id,
gen_constr_prefix) > 0)
@@ -71,17 +85,22 @@ R"===(PROCEDURE RENAME_CONSTRAINT_IDS () IS
CONCAT(:new_table_utf8,
SUBSTR(foreign_id, offset, id_len - offset));
ELSE
- new_foreign_id :=
- CONCAT(new_db_name,
- SUBSTR(foreign_id, old_db_name_len,
- id_len - old_db_name_len));
+ constr_name_len := id_len - old_db_name_len;
+ constr_name := SUBSTR(foreign_id, old_db_name_len,
+ constr_name_len);
+ IF (:new_is_tmp > 0) THEN
+ new_foreign_id := CONCAT(new_db_name, ')===" "/\xFF\xFF" R"===(',
+ SUBSTR(constr_name, 1, constr_name_len - 1));
+ ELSE
+ new_foreign_id := CONCAT(new_db_name, constr_name);
+ END IF;
END IF;
UPDATE SYS_FOREIGN
SET ID = new_foreign_id
- WHERE ID = foreign_id;
+ WHERE ID = foreign_id2;
UPDATE SYS_FOREIGN_COLS
SET ID = new_foreign_id
- WHERE ID = foreign_id;
+ WHERE ID = foreign_id2;
END IF;
END IF;
END LOOP;
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 5cc86dac24a..22a302f5de1 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -2709,6 +2709,14 @@ row_rename_table_for_mysql(
}
pars_info_add_str_literal(info, "new_table_utf8", new_table_name);
+ /* Old foreign ID for temporary constraint was written like this:
+ db_name/\xFFconstraint_name */
+ pars_info_add_int4_literal(info, "old_is_tmp",
+ (fk == RENAME_FK) && old_is_tmp);
+ /* New foreign ID for temporary constraint is written like this:
+ db_name/\xFF\xFFconstraint_name */
+ pars_info_add_int4_literal(info, "new_is_tmp",
+ (fk == RENAME_FK) && new_is_tmp);
err = que_eval_sql(info, rename_constraint_ids, trx);