Commit 040027c8 authored by Jan Lindström's avatar Jan Lindström

MDEV-7627 :Some symbols in table name can cause to Error Code: 1050

when created FK

Analysis: Table name is on filename charset but foreign key
identifiers are not. This lead incorrect foreign key
identifier number to be used.

Fix: Convert foreign key identifier to filename charset before
comparing it to table name when largest foreign key identifier
number is resolved.
parent 6fc0a8af
...@@ -67,3 +67,78 @@ Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key c ...@@ -67,3 +67,78 @@ Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key c
Warning 1215 Cannot add foreign key constraint Warning 1215 Cannot add foreign key constraint
drop table t2; drop table t2;
drop table t1; drop table t1;
CREATE TABLE `#departaments` (
`id_depart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id_depart`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE `#departaments_tree` (
`id_depart` INT(10) UNSIGNED NOT NULL,
`id_depart_in` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id_depart`,`id_depart_in`),
CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
ALTER TABLE `#departaments_tree`
ADD FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments`(`id_depart`);
SHOW CREATE TABLE `#departaments_tree`;
Table Create Table
#departaments_tree CREATE TABLE `#departaments_tree` (
`id_depart` int(10) unsigned NOT NULL,
`id_depart_in` int(10) unsigned NOT NULL,
PRIMARY KEY (`id_depart`,`id_depart_in`),
KEY `id_depart_in` (`id_depart_in`),
CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`),
CONSTRAINT `#departaments_tree_ibfk_2` FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments` (`id_depart`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE `#departaments_tree`;
DROP TABLE `#departaments`;
CREATE TABLE `boroda` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`a` INT(11) UNSIGNED DEFAULT NULL,
`b` INT(11) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
ALTER TABLE `boroda`
ADD FOREIGN KEY (`b`) REFERENCES `boroda`(`id`);
ALTER TABLE `boroda` DROP FOREIGN KEY `boroda_ibfk_2`;
RENAME TABLE `boroda` TO `#boroda`;
ALTER TABLE `#boroda`
ADD FOREIGN KEY (`b`) REFERENCES `#boroda`(`id`);
SHOW CREATE TABLE `#boroda`;
Table Create Table
#boroda CREATE TABLE `#boroda` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`a` int(11) unsigned DEFAULT NULL,
`b` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`),
CONSTRAINT `#boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `#boroda` (`id`),
CONSTRAINT `#boroda_ibfk_2` FOREIGN KEY (`b`) REFERENCES `#boroda` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE `#boroda`;
CREATE TABLE `boroda` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`a` INT(11) UNSIGNED DEFAULT NULL,
`b` INT(11) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
RENAME TABLE `boroda` TO `bor#oda`;
ALTER TABLE `bor#oda`
ADD FOREIGN KEY (`b`) REFERENCES `bor#oda`(`id`);
SHOW CREATE TABLE `bor#oda`;
Table Create Table
bor#oda CREATE TABLE `bor#oda` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`a` int(11) unsigned DEFAULT NULL,
`b` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`),
CONSTRAINT `bor#oda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `bor#oda` (`id`),
CONSTRAINT `bor#oda_ibfk_2` FOREIGN KEY (`b`) REFERENCES `bor#oda` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
DROP TABLE `bor#oda`;
...@@ -124,3 +124,66 @@ show warnings; ...@@ -124,3 +124,66 @@ show warnings;
drop table t2; drop table t2;
drop table t1; drop table t1;
#
# MDEV-7627: Some symbols in table name can cause to Error Code: 1050 when created FK
#
CREATE TABLE `#departaments` (
`id_depart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id_depart`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
CREATE TABLE `#departaments_tree` (
`id_depart` INT(10) UNSIGNED NOT NULL,
`id_depart_in` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id_depart`,`id_depart_in`),
CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
ALTER TABLE `#departaments_tree`
ADD FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments`(`id_depart`);
SHOW CREATE TABLE `#departaments_tree`;
DROP TABLE `#departaments_tree`;
DROP TABLE `#departaments`;
CREATE TABLE `boroda` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`a` INT(11) UNSIGNED DEFAULT NULL,
`b` INT(11) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
ALTER TABLE `boroda`
ADD FOREIGN KEY (`b`) REFERENCES `boroda`(`id`);
ALTER TABLE `boroda` DROP FOREIGN KEY `boroda_ibfk_2`;
RENAME TABLE `boroda` TO `#boroda`;
ALTER TABLE `#boroda`
ADD FOREIGN KEY (`b`) REFERENCES `#boroda`(`id`);
SHOW CREATE TABLE `#boroda`;
DROP TABLE `#boroda`;
CREATE TABLE `boroda` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`a` INT(11) UNSIGNED DEFAULT NULL,
`b` INT(11) UNSIGNED DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`),
CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
RENAME TABLE `boroda` TO `bor#oda`;
ALTER TABLE `bor#oda`
ADD FOREIGN KEY (`b`) REFERENCES `bor#oda`(`id`);
SHOW CREATE TABLE `bor#oda`;
DROP TABLE `bor#oda`;
...@@ -4110,16 +4110,25 @@ dict_table_get_highest_foreign_id( ...@@ -4110,16 +4110,25 @@ dict_table_get_highest_foreign_id(
for (dict_foreign_set::iterator it = table->foreign_set.begin(); for (dict_foreign_set::iterator it = table->foreign_set.begin();
it != table->foreign_set.end(); it != table->foreign_set.end();
++it) { ++it) {
char fkid[MAX_TABLE_NAME_LEN+20];
foreign = *it; foreign = *it;
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len strcpy(fkid, foreign->id);
&& 0 == ut_memcmp(foreign->id, table->name, len) /* Convert foreign key identifier on dictionary memory
&& 0 == ut_memcmp(foreign->id + len, cache to filename charset. */
innobase_convert_to_filename_charset(
strchr(fkid, '/') + 1,
strchr(foreign->id, '/') + 1,
MAX_TABLE_NAME_LEN);
if (ut_strlen(fkid) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(fkid, table->name, len)
&& 0 == ut_memcmp(fkid + len,
dict_ibfk, (sizeof dict_ibfk) - 1) dict_ibfk, (sizeof dict_ibfk) - 1)
&& foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') { && fkid[len + ((sizeof dict_ibfk) - 1)] != '0') {
/* It is of the >= 4.0.18 format */ /* It is of the >= 4.0.18 format */
id = strtoul(foreign->id + len id = strtoul(fkid + len
+ ((sizeof dict_ibfk) - 1), + ((sizeof dict_ibfk) - 1),
&endp, 10); &endp, 10);
if (*endp == '\0') { if (*endp == '\0') {
......
...@@ -4114,16 +4114,25 @@ dict_table_get_highest_foreign_id( ...@@ -4114,16 +4114,25 @@ dict_table_get_highest_foreign_id(
for (dict_foreign_set::iterator it = table->foreign_set.begin(); for (dict_foreign_set::iterator it = table->foreign_set.begin();
it != table->foreign_set.end(); it != table->foreign_set.end();
++it) { ++it) {
char fkid[MAX_TABLE_NAME_LEN+20];
foreign = *it; foreign = *it;
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len strcpy(fkid, foreign->id);
&& 0 == ut_memcmp(foreign->id, table->name, len) /* Convert foreign key identifier on dictionary memory
&& 0 == ut_memcmp(foreign->id + len, cache to filename charset. */
innobase_convert_to_filename_charset(
strchr(fkid, '/') + 1,
strchr(foreign->id, '/') + 1,
MAX_TABLE_NAME_LEN);
if (ut_strlen(fkid) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(fkid, table->name, len)
&& 0 == ut_memcmp(fkid + len,
dict_ibfk, (sizeof dict_ibfk) - 1) dict_ibfk, (sizeof dict_ibfk) - 1)
&& foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') { && fkid[len + ((sizeof dict_ibfk) - 1)] != '0') {
/* It is of the >= 4.0.18 format */ /* It is of the >= 4.0.18 format */
id = strtoul(foreign->id + len id = strtoul(fkid + len
+ ((sizeof dict_ibfk) - 1), + ((sizeof dict_ibfk) - 1),
&endp, 10); &endp, 10);
if (*endp == '\0') { if (*endp == '\0') {
......
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