Skip to content

Commit 03977e8

Browse files
kevgsdr-m
authored andcommitted
MDEV-13671 InnoDB should use case-insensitive column name comparisons like the rest of the server
Problem affects INPLACE ALTER rename columns. innobase_rename_column_try(): some strcmp() was replaced with my_strcasecmp(), queries to update data dictionary was updated to not match column name case.
1 parent f0cb21e commit 03977e8

File tree

6 files changed

+261
-46
lines changed

6 files changed

+261
-46
lines changed

mysql-test/suite/innodb/r/innodb-alter.result

Lines changed: 131 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ t2 CREATE TABLE `t2` (
714714
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c2`) REFERENCES `t1` (`c1`)
715715
) ENGINE=InnoDB DEFAULT CHARSET=latin1
716716
ALTER TABLE t1 CHANGE COLUMN c1 C1 INT;
717+
ALTER TABLE t2 CHANGE COLUMN c2 C2 INT;
717718
SHOW CREATE TABLE t1;
718719
Table Create Table
719720
t1 CREATE TABLE `t1` (
@@ -723,24 +724,147 @@ t1 CREATE TABLE `t1` (
723724
SHOW CREATE TABLE t2;
724725
Table Create Table
725726
t2 CREATE TABLE `t2` (
726-
`c2` int(11) NOT NULL,
727-
KEY `c2` (`c2`),
727+
`C2` int(11) DEFAULT NULL,
728+
KEY `c2` (`C2`),
728729
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c2`) REFERENCES `t1` (`c1`)
729730
) ENGINE=InnoDB DEFAULT CHARSET=latin1
731+
ALTER TABLE t1 CHANGE COLUMN C1 c5 INT;
732+
ALTER TABLE t2 CHANGE COLUMN C2 c6 INT;
730733
SHOW CREATE TABLE t1;
731734
Table Create Table
732735
t1 CREATE TABLE `t1` (
733-
`C1` int(11) NOT NULL DEFAULT '0',
734-
PRIMARY KEY (`C1`)
736+
`c5` int(11) NOT NULL DEFAULT '0',
737+
PRIMARY KEY (`c5`)
735738
) ENGINE=InnoDB DEFAULT CHARSET=latin1
736739
SHOW CREATE TABLE t2;
737740
Table Create Table
738741
t2 CREATE TABLE `t2` (
739-
`c2` int(11) NOT NULL,
740-
KEY `c2` (`c2`),
741-
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c2`) REFERENCES `t1` (`c1`)
742+
`c6` int(11) DEFAULT NULL,
743+
KEY `c2` (`c6`),
744+
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c6`) REFERENCES `t1` (`c5`)
742745
) ENGINE=InnoDB DEFAULT CHARSET=latin1
746+
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
747+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
748+
WHERE T.NAME='test/t1';
749+
NAME
750+
c5
751+
SELECT F.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_FIELDS F INNER JOIN
752+
INFORMATION_SCHEMA.INNODB_SYS_INDEXES I ON F.INDEX_ID=I.INDEX_ID INNER JOIN
753+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON I.TABLE_ID=T.TABLE_ID
754+
WHERE T.NAME='test/t1' AND I.NAME='PRIMARY';
755+
NAME
756+
c5
757+
SELECT C.REF_COL_NAME, C.FOR_COL_NAME FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS C INNER JOIN
758+
INFORMATION_SCHEMA.INNODB_SYS_FOREIGN F ON C.ID=F.ID
759+
WHERE F.FOR_NAME='test/t2';
760+
REF_COL_NAME FOR_COL_NAME
761+
c5 c6
743762
DROP TABLE t2, t1;
763+
# virtual columns case too
764+
CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a) VIRTUAL) ENGINE = InnoDB;
765+
ALTER TABLE t1 CHANGE COLUMN a A INT;
766+
SHOW CREATE TABLE t1;
767+
Table Create Table
768+
t1 CREATE TABLE `t1` (
769+
`A` int(11) DEFAULT NULL,
770+
`b` int(11) AS (a) VIRTUAL
771+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
772+
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
773+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
774+
WHERE T.NAME='test/t1';
775+
NAME
776+
a
777+
DROP TABLE t1;
778+
# different FOREIGN KEY cases
779+
CREATE TABLE t1 (
780+
a INT UNIQUE KEY,
781+
b INT UNIQUE KEY,
782+
c INT UNIQUE KEY,
783+
d INT UNIQUE KEY
784+
) ENGINE=INNODB;
785+
CREATE TABLE t2 (
786+
aa INT,
787+
bb INT,
788+
cc INT,
789+
dd INT
790+
) ENGINE=INNODB;
791+
INSERT INTO t1 VALUES (1, 1, 1, 1);
792+
INSERT INTO t2 VALUES (1, 1, 1, 1);
793+
ALTER TABLE t1 CHANGE a A INT, ALGORITHM=INPLACE;
794+
ALTER TABLE t1 CHANGE c C INT, ALGORITHM=INPLACE;
795+
ALTER TABLE t2 CHANGE cc CC INT, ALGORITHM=INPLACE;
796+
ALTER TABLE t2 CHANGE dd DD INT, ALGORITHM=INPLACE;
797+
SET foreign_key_checks=0;
798+
ALTER TABLE t2
799+
ADD FOREIGN KEY(aa) REFERENCES t1(a),
800+
ADD FOREIGN KEY(bb) REFERENCES t1(b),
801+
ADD FOREIGN KEY(cc) REFERENCES t1(c),
802+
ADD FOREIGN KEY(dd) REFERENCES t1(d),
803+
ALGORITHM=INPLACE;
804+
ALTER TABLE t1 CHANGE b B INT, ALGORITHM=INPLACE;
805+
ALTER TABLE t2 CHANGE aa AA INT, ALGORITHM=INPLACE;
806+
ALTER TABLE t1 CHANGE d D INT, ALGORITHM=INPLACE;
807+
ALTER TABLE t2 CHANGE bb BB INT, ALGORITHM=INPLACE;
808+
SHOW CREATE TABLE t1;
809+
Table Create Table
810+
t1 CREATE TABLE `t1` (
811+
`A` int(11) DEFAULT NULL,
812+
`B` int(11) DEFAULT NULL,
813+
`C` int(11) DEFAULT NULL,
814+
`D` int(11) DEFAULT NULL,
815+
UNIQUE KEY `a` (`A`),
816+
UNIQUE KEY `b` (`B`),
817+
UNIQUE KEY `c` (`C`),
818+
UNIQUE KEY `d` (`D`)
819+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
820+
SHOW CREATE TABLE t2;
821+
Table Create Table
822+
t2 CREATE TABLE `t2` (
823+
`AA` int(11) DEFAULT NULL,
824+
`BB` int(11) DEFAULT NULL,
825+
`CC` int(11) DEFAULT NULL,
826+
`DD` int(11) DEFAULT NULL,
827+
KEY `aa` (`AA`),
828+
KEY `bb` (`BB`),
829+
KEY `CC` (`CC`),
830+
KEY `DD` (`DD`),
831+
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`),
832+
CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`bb`) REFERENCES `t1` (`b`),
833+
CONSTRAINT `t2_ibfk_3` FOREIGN KEY (`cc`) REFERENCES `t1` (`c`),
834+
CONSTRAINT `t2_ibfk_4` FOREIGN KEY (`dd`) REFERENCES `t1` (`d`)
835+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
836+
DELETE FROM t1 WHERE a=1;
837+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
838+
DELETE FROM t1 WHERE A=1;
839+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
840+
DELETE FROM t1 WHERE b=1;
841+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
842+
DELETE FROM t1 WHERE B=1;
843+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
844+
DELETE FROM t1 WHERE c=1;
845+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
846+
DELETE FROM t1 WHERE C=1;
847+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
848+
DELETE FROM t1 WHERE d=1;
849+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
850+
DELETE FROM t1 WHERE D=1;
851+
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`aa`) REFERENCES `t1` (`a`))
852+
DROP TABLE t2, t1;
853+
# virtual columns case too
854+
CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a) VIRTUAL) ENGINE = InnoDB;
855+
ALTER TABLE t1 CHANGE COLUMN a A INT;
856+
SHOW CREATE TABLE t1;
857+
Table Create Table
858+
t1 CREATE TABLE `t1` (
859+
`A` int(11) DEFAULT NULL,
860+
`b` int(11) AS (a) VIRTUAL
861+
) ENGINE=InnoDB DEFAULT CHARSET=latin1
862+
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
863+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
864+
WHERE T.NAME='test/t1';
865+
NAME
866+
a
867+
DROP TABLE t1;
744868
#
745869
# BUG 20029625 - HANDLE_FATAL_SIGNAL (SIG=11) IN
746870
# DICT_MEM_TABLE_COL_RENAME_LOW

mysql-test/suite/innodb/t/innodb-alter.test

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -419,15 +419,110 @@ CREATE TABLE t2(c2 INT NOT NULL, FOREIGN KEY(c2) REFERENCES t1(c1))ENGINE=INNODB
419419
SHOW CREATE TABLE t1;
420420
SHOW CREATE TABLE t2;
421421
ALTER TABLE t1 CHANGE COLUMN c1 C1 INT;
422+
ALTER TABLE t2 CHANGE COLUMN c2 C2 INT;
422423
SHOW CREATE TABLE t1;
423424
SHOW CREATE TABLE t2;
424-
# FIXME: MDEV-13671 InnoDB should use case-insensitive column name comparisons
425-
# like the rest of the server
426-
#ALTER TABLE t1 CHANGE COLUMN C1 c5 INT;
425+
ALTER TABLE t1 CHANGE COLUMN C1 c5 INT;
426+
ALTER TABLE t2 CHANGE COLUMN C2 c6 INT;
427427
SHOW CREATE TABLE t1;
428428
SHOW CREATE TABLE t2;
429+
430+
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
431+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
432+
WHERE T.NAME='test/t1';
433+
434+
SELECT F.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_FIELDS F INNER JOIN
435+
INFORMATION_SCHEMA.INNODB_SYS_INDEXES I ON F.INDEX_ID=I.INDEX_ID INNER JOIN
436+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON I.TABLE_ID=T.TABLE_ID
437+
WHERE T.NAME='test/t1' AND I.NAME='PRIMARY';
438+
439+
SELECT C.REF_COL_NAME, C.FOR_COL_NAME FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS C INNER JOIN
440+
INFORMATION_SCHEMA.INNODB_SYS_FOREIGN F ON C.ID=F.ID
441+
WHERE F.FOR_NAME='test/t2';
442+
443+
DROP TABLE t2, t1;
444+
--echo # virtual columns case too
445+
CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a) VIRTUAL) ENGINE = InnoDB;
446+
ALTER TABLE t1 CHANGE COLUMN a A INT;
447+
SHOW CREATE TABLE t1;
448+
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
449+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
450+
WHERE T.NAME='test/t1';
451+
DROP TABLE t1;
452+
453+
454+
--echo # different FOREIGN KEY cases
455+
CREATE TABLE t1 (
456+
a INT UNIQUE KEY,
457+
b INT UNIQUE KEY,
458+
c INT UNIQUE KEY,
459+
d INT UNIQUE KEY
460+
) ENGINE=INNODB;
461+
CREATE TABLE t2 (
462+
aa INT,
463+
bb INT,
464+
cc INT,
465+
dd INT
466+
) ENGINE=INNODB;
467+
468+
INSERT INTO t1 VALUES (1, 1, 1, 1);
469+
INSERT INTO t2 VALUES (1, 1, 1, 1);
470+
471+
ALTER TABLE t1 CHANGE a A INT, ALGORITHM=INPLACE;
472+
ALTER TABLE t1 CHANGE c C INT, ALGORITHM=INPLACE;
473+
ALTER TABLE t2 CHANGE cc CC INT, ALGORITHM=INPLACE;
474+
ALTER TABLE t2 CHANGE dd DD INT, ALGORITHM=INPLACE;
475+
476+
SET foreign_key_checks=0;
477+
ALTER TABLE t2
478+
ADD FOREIGN KEY(aa) REFERENCES t1(a),
479+
ADD FOREIGN KEY(bb) REFERENCES t1(b),
480+
ADD FOREIGN KEY(cc) REFERENCES t1(c),
481+
ADD FOREIGN KEY(dd) REFERENCES t1(d),
482+
ALGORITHM=INPLACE;
483+
484+
ALTER TABLE t1 CHANGE b B INT, ALGORITHM=INPLACE;
485+
ALTER TABLE t2 CHANGE aa AA INT, ALGORITHM=INPLACE;
486+
487+
--source include/restart_mysqld.inc
488+
489+
ALTER TABLE t1 CHANGE d D INT, ALGORITHM=INPLACE;
490+
ALTER TABLE t2 CHANGE bb BB INT, ALGORITHM=INPLACE;
491+
SHOW CREATE TABLE t1;
492+
SHOW CREATE TABLE t2;
493+
494+
--error ER_ROW_IS_REFERENCED_2
495+
DELETE FROM t1 WHERE a=1;
496+
--error ER_ROW_IS_REFERENCED_2
497+
DELETE FROM t1 WHERE A=1;
498+
499+
--error ER_ROW_IS_REFERENCED_2
500+
DELETE FROM t1 WHERE b=1;
501+
--error ER_ROW_IS_REFERENCED_2
502+
DELETE FROM t1 WHERE B=1;
503+
504+
--error ER_ROW_IS_REFERENCED_2
505+
DELETE FROM t1 WHERE c=1;
506+
--error ER_ROW_IS_REFERENCED_2
507+
DELETE FROM t1 WHERE C=1;
508+
509+
--error ER_ROW_IS_REFERENCED_2
510+
DELETE FROM t1 WHERE d=1;
511+
--error ER_ROW_IS_REFERENCED_2
512+
DELETE FROM t1 WHERE D=1;
513+
429514
DROP TABLE t2, t1;
430515

516+
--echo # virtual columns case too
517+
CREATE TABLE t1 (a INT, b INT GENERATED ALWAYS AS (a) VIRTUAL) ENGINE = InnoDB;
518+
ALTER TABLE t1 CHANGE COLUMN a A INT;
519+
SHOW CREATE TABLE t1;
520+
SELECT C.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS C INNER JOIN
521+
INFORMATION_SCHEMA.INNODB_SYS_TABLES T ON C.TABLE_ID=T.TABLE_ID
522+
WHERE T.NAME='test/t1';
523+
DROP TABLE t1;
524+
525+
431526
--echo #
432527
--echo # BUG 20029625 - HANDLE_FATAL_SIGNAL (SIG=11) IN
433528
--echo # DICT_MEM_TABLE_COL_RENAME_LOW

storage/innobase/dict/dict0mem.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,9 +498,7 @@ dict_mem_table_col_rename(
498498
s += len + 1;
499499
}
500500

501-
/* This could fail if the data dictionaries are out of sync.
502-
Proceed with the renaming anyway. */
503-
ut_ad(!strcmp(from, s));
501+
ut_ad(!my_strcasecmp(system_charset_info, from, s));
504502

505503
dict_mem_table_col_rename_low(table, nth_col, to, s);
506504
}

0 commit comments

Comments
 (0)