diff --git a/mysql-test/suite/innodb/r/change_column_collation.result b/mysql-test/suite/innodb/r/change_column_collation.result index fa1df1df830..54eff706276 100644 --- a/mysql-test/suite/innodb/r/change_column_collation.result +++ b/mysql-test/suite/innodb/r/change_column_collation.result @@ -9,11 +9,89 @@ msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_swedish_ci UNIQUE ) ENGINE=INNODB; INSERT INTO t1 VALUES (1, 'aaa'); INSERT INTO t1 VALUES (2, 'ååå'); -ALTER TABLE t1 -MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, -ALGORITHM=NOCOPY; -ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -ALTER TABLE t1 DROP INDEX msg, -MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, -ALGORITHM=NOCOPY; +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=inplace; +ERROR 23000: Duplicate entry 'NULL' for key 'msg' +DROP TABLE t1; +CREATE TABLE t1 ( +id INT PRIMARY KEY, +msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, +id_2 INT not null, +unique index(msg, id_2) +) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 'aaa', 2); +INSERT INTO t1 VALUES (2, 'AAA', 3); +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=inplace; +DROP TABLE t1; +CREATE TABLE t1 ( +id INT PRIMARY KEY, +msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, +unique index(msg) +) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 'aaa'); +INSERT INTO t1 VALUES (2, 'bbb'); +INSERT INTO t1 VALUES (3, 'ccc'); +SET DEBUG_SYNC = 'RESET'; +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL before_apply WAIT_FOR go_ahead'; +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY; +connect con1,localhost,root,,; +connection con1; +SET DEBUG_SYNC = 'now WAIT_FOR before_apply'; +INSERT INTO t1 VALUES (4, 'AAA'); +UPDATE t1 set msg = "ddd" where id = 2; +DELETE FROM t1 WHERE id= 3; +SET DEBUG_SYNC = 'now SIGNAL go_ahead'; +SET DEBUG_SYNC = 'RESET'; +connection default; +ERROR 23000: Duplicate entry 'NULL' for key 'msg' +SELECT * FROM t1; +id msg +4 AAA +1 aaa +2 ddd +DROP TABLE t1; +CREATE TABLE t1 ( +id INT PRIMARY KEY, +msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, +unique index(msg) +) ENGINE=INNODB; +INSERT INTO t1 VALUES (1, 'aaa'); +SET DEBUG_DBUG="+d,create_index_fail"; +SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR con1_go"; +BEGIN; +SELECT * FROM t1; +id msg +1 aaa +SET DEBUG_SYNC="now SIGNAL alter_signal"; +connection default; +ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +connection con1; +rollback; +INSERT INTO t1 VALUES(2, 'bbb'); +disconnect con1; +connection default; +SET DEBUG_SYNC=reset; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `id` int(11) NOT NULL, + `msg` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `msg` (`msg`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(3, 'ccc'); +DROP TABLE t1; +CREATE TABLE t1(id INT PRIMARY KEY, msg VARCHAR(100), +msg_1 VARCHAR(100) AS (msg) VIRTUAL, +msg_2 VARCHAR(100) AS (msg) STORED, +UNIQUE(msg), UNIQUE(msg_1), +UNIQUE(msg_2))ENGINE=InnoDB; +ALTER TABLE t1 MODIFY msg_1 VARCHAR(100) CHARACTER SET utf8 +COLLATE utf8_unicode_ci, ALGORITHM=inplace; +ERROR HY000: This is not yet supported for generated columns +ALTER TABLE t1 MODIFY msg_2 VARCHAR(100) CHARACTER SET utf8 +COLLATE utf8_unicode_ci, ALGORITHM=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff b/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff index dd4caf125af..90846ac4644 100644 --- a/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff @@ -1,4 +1,4 @@ -@@ -288,7 +288,6 @@ +@@ -279,7 +279,6 @@ alter table boundary_255 modify a varchar(70) charset utf8mb4, algorithm=instant; @@ -6,7 +6,7 @@ drop table boundary_255; create table t ( a char(10) collate utf8mb3_general_ci, -@@ -306,35 +305,21 @@ +@@ -297,32 +296,21 @@ repeat('a', 10), repeat('a', 10) ); alter table t modify a char(10) collate utf8mb4_general_ci, algorithm=instant; @@ -25,19 +25,16 @@ -test.t check status OK +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY alter table t modify aa char(10) collate utf8mb4_general_ci, algorithm=instant; --ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -check table t; -Table Op Msg_type Msg_text -test.t check status OK +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY alter table t modify bb char(70) collate utf8mb4_general_ci, algorithm=instant; --ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -check table t; -Table Op Msg_type Msg_text -test.t check status OK +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY alter table t modify cc char(100) collate utf8mb4_general_ci, algorithm=instant; --ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -check table t; -Table Op Msg_type Msg_text -test.t check status OK @@ -45,10 +42,17 @@ alter table t modify d char(10) collate utf8mb4_spanish_ci, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY alter table t modify dd char(10) collate utf8mb4_spanish_ci, algorithm=instant; --ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY select * from t; a b c aa bb cc d dd aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaa - -mysqltest: Result length mismatch +@@ -2066,7 +2054,7 @@ + ALTER TABLE t1 + CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci, + ADD UNIQUE INDEX test_key (a); +-ERROR 23000: Duplicate entry 'NULL' for key 'test_key' ++ERROR 23000: Duplicate entry 'a1' for key 'test_key' + ALTER TABLE t1 CONVERT TO CHARACTER SET UTF8MB4 COLLATE UTF8MB4_UNICODE_520_CI; + CHECK TABLE t1; + Table Op Msg_type Msg_text diff --git a/mysql-test/suite/innodb/r/instant_alter_charset.result b/mysql-test/suite/innodb/r/instant_alter_charset.result index f999697a329..caca0640566 100644 --- a/mysql-test/suite/innodb/r/instant_alter_charset.result +++ b/mysql-test/suite/innodb/r/instant_alter_charset.result @@ -199,15 +199,6 @@ a varchar(150) charset utf8mb3 unique key alter table key_part_bug modify a varchar(150) charset utf8mb4, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table key_part_bug -modify a varchar(150) charset utf8mb4, -algorithm=nocopy; -ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table key_part_bug -drop index a, -modify a varchar(150) charset utf8mb4, -algorithm=nocopy; drop table key_part_bug; create table latin1_swedish_special_case ( copy1 varchar(150) charset ascii collate ascii_general_ci, @@ -318,23 +309,20 @@ check table t; Table Op Msg_type Msg_text test.t check status OK alter table t modify aa char(10) collate utf8mb4_general_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY check table t; Table Op Msg_type Msg_text test.t check status OK alter table t modify bb char(70) collate utf8mb4_general_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY check table t; Table Op Msg_type Msg_text test.t check status OK alter table t modify cc char(100) collate utf8mb4_general_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY check table t; Table Op Msg_type Msg_text test.t check status OK alter table t modify d char(10) collate utf8mb4_spanish_ci, algorithm=instant; alter table t modify dd char(10) collate utf8mb4_spanish_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY select * from t; a b c aa bb cc d dd aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaa @@ -390,10 +378,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_general_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_general_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_general_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -407,10 +391,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_bin, modify b varchar(50) charset utf8mb4 collate utf8mb4_bin, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_bin, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -424,10 +404,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -441,10 +417,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_icelandic_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_icelandic_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_icelandic_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -458,10 +430,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_latvian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_latvian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_latvian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -475,10 +443,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_romanian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_romanian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_romanian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -492,10 +456,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_slovenian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_slovenian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_slovenian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -509,10 +469,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_polish_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_polish_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_polish_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -526,10 +482,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_estonian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_estonian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_estonian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -543,10 +495,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_spanish_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_spanish_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_spanish_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -560,10 +508,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_swedish_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_swedish_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_swedish_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -577,10 +521,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_turkish_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_turkish_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_turkish_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -594,10 +534,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_czech_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_czech_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_czech_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -611,10 +547,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -628,10 +560,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_lithuanian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_lithuanian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_lithuanian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -645,10 +573,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_slovak_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_slovak_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_slovak_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -662,10 +586,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_spanish2_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_spanish2_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_spanish2_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -679,10 +599,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_roman_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_roman_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_roman_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -696,10 +612,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -713,10 +625,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_esperanto_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_esperanto_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_esperanto_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -730,10 +638,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_hungarian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_hungarian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_hungarian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -747,10 +651,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_sinhala_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_sinhala_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_sinhala_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -764,10 +664,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -781,10 +677,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_croatian_mysql561_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_croatian_mysql561_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_croatian_mysql561_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -798,10 +690,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -815,10 +703,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -832,10 +716,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_croatian_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_croatian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_croatian_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -849,10 +729,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_myanmar_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_myanmar_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_myanmar_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -866,10 +742,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2, modify b varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -883,10 +755,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_general_nopad_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_general_nopad_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_general_nopad_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -900,10 +768,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_nopad_bin, modify b varchar(50) charset utf8mb4 collate utf8mb4_nopad_bin, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_nopad_bin, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -917,10 +781,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_nopad_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_nopad_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_nopad_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -934,10 +794,6 @@ alter table tmp change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_nopad_ci, modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_nopad_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table tmp -change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_nopad_ci, -algorithm=instant; check table tmp; Table Op Msg_type Msg_text test.tmp check status OK @@ -974,7 +830,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; @@ -991,7 +847,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; @@ -1008,7 +864,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; @@ -1025,7 +881,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, algorithm=instant; @@ -1042,7 +898,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset ascii collate ascii_bin, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset ascii collate ascii_bin, algorithm=instant; @@ -1059,7 +915,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci, algorithm=instant; @@ -1076,7 +932,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, algorithm=instant; @@ -1093,7 +949,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, algorithm=instant; @@ -1110,7 +966,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci, algorithm=instant; @@ -1127,7 +983,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset latin1 collate latin1_general_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset latin1 collate latin1_general_ci, algorithm=instant; @@ -1144,7 +1000,7 @@ algorithm=instant; alter table tmp modify b varchar(50) charset utf16 collate utf16_german2_ci, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table tmp modify c varchar(50) charset utf16 collate utf16_german2_ci, algorithm=instant; @@ -2031,11 +1887,8 @@ insert into t values alter table t modify a char(10) collate latin1_general_cs, algorithm=inplace; ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY alter table t modify b char(10) collate latin1_general_cs, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table t modify b char(10) collate latin1_general_cs, algorithm=nocopy; -ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table t modify b char(10) collate latin1_general_cs, -drop index b_key, algorithm=nocopy; check table t; Table Op Msg_type Msg_text test.t check status OK @@ -2055,11 +1908,8 @@ insert into t values alter table t modify a varchar(10) collate latin1_general_cs, algorithm=inplace; ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY alter table t modify b varchar(10) collate latin1_general_cs, algorithm=instant; -ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY alter table t modify b varchar(10) collate latin1_general_cs, algorithm=nocopy; -ERROR 0A000: ALGORITHM=NOCOPY is not supported. Reason: Collation change on an indexed column. Try ALGORITHM=COPY -alter table t modify b varchar(10) collate latin1_general_cs, -drop index b_key, algorithm=nocopy; check table t; Table Op Msg_type Msg_text test.t check status OK @@ -2201,7 +2051,7 @@ INSERT INTO t1 VALUES (1, 'a1'), (2, 'a1'); ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci, ADD UNIQUE INDEX test_key (a); -ERROR 23000: Duplicate entry 'a1' for key 'test_key' +ERROR 23000: Duplicate entry 'NULL' for key 'test_key' ALTER TABLE t1 CONVERT TO CHARACTER SET UTF8MB4 COLLATE UTF8MB4_UNICODE_520_CI; CHECK TABLE t1; Table Op Msg_type Msg_text @@ -2216,7 +2066,7 @@ INSERT INTO t1 VALUES (1, 'a1'), (2, 'a1'); ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_520_ci, ADD UNIQUE INDEX test_key (a); -ERROR 23000: Duplicate entry 'a1' for key 'test_key' +ERROR 23000: Duplicate entry 'NULL' for key 'test_key' ALTER TABLE t1 CONVERT TO CHARACTER SET UTF8MB4 COLLATE UTF8MB4_UNICODE_520_CI; CHECK TABLE t1; Table Op Msg_type Msg_text diff --git a/mysql-test/suite/innodb/t/change_column_collation.test b/mysql-test/suite/innodb/t/change_column_collation.test index 1ba519535bd..7d82aac7ec2 100644 --- a/mysql-test/suite/innodb/t/change_column_collation.test +++ b/mysql-test/suite/innodb/t/change_column_collation.test @@ -1,4 +1,8 @@ --source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +--source include/count_sessions.inc --echo # --echo # MDEV-26294 Duplicate entries in unique index not detected when @@ -14,11 +18,108 @@ CREATE TABLE t1 ( ) ENGINE=INNODB; INSERT INTO t1 VALUES (1, 'aaa'); INSERT INTO t1 VALUES (2, 'ååå'); ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON -ALTER TABLE t1 -MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, -ALGORITHM=NOCOPY; -ALTER TABLE t1 DROP INDEX msg, -MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, -ALGORITHM=NOCOPY; +--error ER_DUP_ENTRY +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=inplace; DROP TABLE t1; + +# PageBulk insert shouldn't fail like records are not in ascending order + +CREATE TABLE t1 ( + id INT PRIMARY KEY, + msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, + id_2 INT not null, + unique index(msg, id_2) +) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 'aaa', 2); +INSERT INTO t1 VALUES (2, 'AAA', 3); + +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=inplace; + +DROP TABLE t1; + +# Detect the duplicate entry from concurrent DML + +CREATE TABLE t1 ( + id INT PRIMARY KEY, + msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, + unique index(msg) +) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 'aaa'); +INSERT INTO t1 VALUES (2, 'bbb'); +INSERT INTO t1 VALUES (3, 'ccc'); + +SET DEBUG_SYNC = 'RESET'; +SET DEBUG_SYNC = 'row_log_apply_before SIGNAL before_apply WAIT_FOR go_ahead'; +--send +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY; + +connect (con1,localhost,root,,); +connection con1; + +SET DEBUG_SYNC = 'now WAIT_FOR before_apply'; +INSERT INTO t1 VALUES (4, 'AAA'); +UPDATE t1 set msg = "ddd" where id = 2; +DELETE FROM t1 WHERE id= 3; +SET DEBUG_SYNC = 'now SIGNAL go_ahead'; +SET DEBUG_SYNC = 'RESET'; + +connection default; + +--error ER_DUP_ENTRY +reap; + +SELECT * FROM t1; +DROP TABLE t1; + +# InnoDB should store the changed collation column into +# change_col_info in index when rollback of alter happens + +CREATE TABLE t1 ( + id INT PRIMARY KEY, + msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin, + unique index(msg) +) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1, 'aaa'); +SET DEBUG_DBUG="+d,create_index_fail"; +SET DEBUG_SYNC="innodb_inplace_alter_table_enter SIGNAL con1_go WAIT_FOR alter_signal"; +--send +ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY; + +connection con1; +SET DEBUG_SYNC="now WAIT_FOR con1_go"; +BEGIN; +SELECT * FROM t1; +SET DEBUG_SYNC="now SIGNAL alter_signal"; +connection default; +--error ER_DUP_ENTRY +reap; +connection con1; +rollback; +INSERT INTO t1 VALUES(2, 'bbb'); +disconnect con1; +connection default; +SET DEBUG_SYNC=reset; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(3, 'ccc'); +DROP TABLE t1; + +# Inplace Collation change is not supported for virtual column +# and stored column + +CREATE TABLE t1(id INT PRIMARY KEY, msg VARCHAR(100), + msg_1 VARCHAR(100) AS (msg) VIRTUAL, + msg_2 VARCHAR(100) AS (msg) STORED, + UNIQUE(msg), UNIQUE(msg_1), + UNIQUE(msg_2))ENGINE=InnoDB; +--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN +ALTER TABLE t1 MODIFY msg_1 VARCHAR(100) CHARACTER SET utf8 + COLLATE utf8_unicode_ci, ALGORITHM=inplace; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t1 MODIFY msg_2 VARCHAR(100) CHARACTER SET utf8 + COLLATE utf8_unicode_ci, ALGORITHM=inplace; +DROP TABLE t1; + +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/instant_alter_charset.test b/mysql-test/suite/innodb/t/instant_alter_charset.test index f0366967ab8..5be4f7a5b83 100644 --- a/mysql-test/suite/innodb/t/instant_alter_charset.test +++ b/mysql-test/suite/innodb/t/instant_alter_charset.test @@ -227,18 +227,9 @@ create table key_part_bug ( a varchar(150) charset utf8mb3 unique key ) engine=innodb; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table key_part_bug modify a varchar(150) charset utf8mb4, algorithm=instant; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON -alter table key_part_bug - modify a varchar(150) charset utf8mb4, - algorithm=nocopy; -alter table key_part_bug - drop index a, - modify a varchar(150) charset utf8mb4, - algorithm=nocopy; drop table key_part_bug; @@ -356,13 +347,10 @@ check table t; alter table t modify c char(100) collate utf8mb4_general_ci, algorithm=instant; check table t; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify aa char(10) collate utf8mb4_general_ci, algorithm=instant; check table t; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify bb char(70) collate utf8mb4_general_ci, algorithm=instant; check table t; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify cc char(100) collate utf8mb4_general_ci, algorithm=instant; check table t; @@ -454,16 +442,11 @@ while ($counter <= $data_size) { insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON eval alter table tmp change a a varchar(50) charset $to_charset collate $to_collate, modify b varchar(50) charset $to_charset collate $to_collate, algorithm=instant; - eval alter table tmp - change a a varchar(50) charset $to_charset collate $to_collate, - algorithm=instant; - check table tmp; drop table tmp; @@ -702,10 +685,7 @@ alter table t modify a char(10) collate latin1_general_cs, algorithm=inplace; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify b char(10) collate latin1_general_cs, algorithm=instant; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify b char(10) collate latin1_general_cs, algorithm=nocopy; -alter table t modify b char(10) collate latin1_general_cs, -drop index b_key, algorithm=nocopy; check table t; alter table t modify c char(10) collate latin1_general_cs, algorithm=instant; @@ -728,10 +708,7 @@ alter table t modify a varchar(10) collate latin1_general_cs, algorithm=inplace; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify b varchar(10) collate latin1_general_cs, algorithm=instant; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter table t modify b varchar(10) collate latin1_general_cs, algorithm=nocopy; -alter table t modify b varchar(10) collate latin1_general_cs, -drop index b_key, algorithm=nocopy; check table t; alter table t modify c varchar(10) collate latin1_general_cs, algorithm=instant; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index fe9138c3ae7..b46d68aac63 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -956,6 +956,41 @@ get_error_key_name( } } +/** Convert field type and length to InnoDB format */ +static void get_type(const Field &f, uint &prtype, uint8_t &mtype, + uint16_t &len) +{ + mtype= get_innobase_type_from_mysql_type(&prtype, &f); + len= static_cast(f.pack_length()); + prtype|= f.type(); + if (f.type() == MYSQL_TYPE_VARCHAR) + { + auto l= static_cast(f).length_bytes; + len= static_cast(len - l); + if (l == 2) + prtype|= DATA_LONG_TRUE_VARCHAR; + } + if (!f.real_maybe_null()) + prtype |= DATA_NOT_NULL; + if (f.binary()) + prtype |= DATA_BINARY_TYPE; + if (f.table->versioned()) + { + if (&f == f.table->field[f.table->s->vers.start_fieldno]) + prtype|= DATA_VERS_START; + else if (&f == f.table->field[f.table->s->vers.end_fieldno]) + prtype|= DATA_VERS_END; + else if (!(f.flags & VERS_UPDATE_UNVERSIONED_FLAG)) + prtype|= DATA_VERSIONED; + } + + if (!f.stored_in_db()) + prtype|= DATA_VIRTUAL; + + if (dtype_is_string_type(mtype)) + prtype|= f.charset()->number << 16; +} + struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx { /** Dummy query graph */ @@ -1050,6 +1085,10 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx /** The page_compression_level attribute, or 0 */ const uint page_compression_level; + /** Indexed columns whose charset-collation is changing + in a way that does not require the table to be rebuilt */ + col_collations change_col_collate; + ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg, dict_index_t** drop_arg, ulint num_to_drop_arg, @@ -1332,6 +1371,85 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx } return true; } + + /** Check whether the column has any change in collation type. + If it is then store the column information in heap + @param index index being added (or rebuilt) + @param altered_table altered table definition */ + void change_col_collation(dict_index_t *index, const TABLE &altered_table) + { + ut_ad(!need_rebuild()); + ut_ad(!index->is_primary()); + ut_ad(!index->is_committed()); + + unsigned n_cols= 0; + for (unsigned i= 0; i < index->n_fields; i++) + { + const char *field_name= index->fields[i].name(); + if (!field_name || !dtype_is_string_type(index->fields[i].col->mtype)) + continue; + for (uint j= 0; j < altered_table.s->fields; j++) + { + const Field *altered_field= altered_table.field[j]; + + if (my_strcasecmp(system_charset_info, field_name, + altered_field->field_name.str)) + continue; + + unsigned prtype; + uint8_t mtype; + uint16_t len; + get_type(*altered_field, prtype, mtype, len); + + if (prtype == index->fields[i].col->prtype) + continue; + auto it= change_col_collate.find(index->fields[i].col->ind); + if (it != change_col_collate.end()) + { + n_cols++; + index->fields[i].col= it->second; + continue; + } + + const CHARSET_INFO *cs= altered_field->charset(); + + dict_col_t *col= + static_cast(mem_heap_alloc(heap, sizeof *col)); + *col= *index->fields[i].col; + col->prtype= prtype; + col->mtype= mtype; + col->mbminlen= cs->mbminlen & 7; + col->mbmaxlen= cs->mbmaxlen & 7; + col->len= len; + index->fields[i].col= col; + n_cols++; + change_col_collate[col->ind]= col; + } + } + + index->init_change_cols(n_cols); + } + + void cleanup_col_collation() + { + ut_ad(old_table == new_table); + if (change_col_collate.empty()) + return; + const dict_index_t *index= dict_table_get_first_index(old_table); + while ((index= dict_table_get_next_index(index)) != nullptr) + { + if (index->is_committed()) + continue; + auto collate_end= change_col_collate.end(); + for (unsigned i= 0, j= 0; i < index->n_fields; i++) + { + const dict_col_t *col= index->fields[i].col; + if (change_col_collate.find(col->ind) == collate_end) + index->fields[i].col= + index->change_col_info->add(index->heap, *col, j++); + } + } + } }; /********************************************************************//** @@ -2345,16 +2463,7 @@ innodb_instant_alter_column_allowed_reason: if (new_field->field) { /* This is an existing column. */ - - if (new_field->field->charset() - == key_part->field->charset()) { - continue; - } - - ha_alter_info->unsupported_reason = - "Collation change on" - " an indexed column"; - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + continue; } /* This is an added column. */ @@ -7061,6 +7170,8 @@ error_handling_drop_uncached: if (n_v_col) { index->assign_new_v_col(n_v_col); } + + ctx->change_col_collation(index, *altered_table); /* Note the id of the transaction that created this index, we use it to restrict readers from accessing this index, to ensure read consistency. */ @@ -8533,7 +8644,9 @@ ok_exit: ctx->add_index, ctx->add_key_numbers, ctx->num_to_add_index, altered_table, ctx->defaults, ctx->col_map, ctx->add_autoinc, ctx->sequence, ctx->skip_pk_sort, - ctx->m_stage, add_v, eval_table, ctx->allow_not_null); + ctx->m_stage, add_v, eval_table, ctx->allow_not_null, + ctx->change_col_collate.empty() + ? nullptr : &ctx->change_col_collate); #ifndef DBUG_OFF oom: @@ -8867,6 +8980,7 @@ inline bool rollback_inplace_alter_table(Alter_inplace_info *ha_alter_info, Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE, ctx->trx, prebuilt->trx); ctx->clean_new_vcol_index(); + ctx->cleanup_col_collation(); ut_d(dict_table_check_for_dup_indexes(ctx->old_table, CHECK_ABORTED_OK)); } @@ -9265,36 +9379,6 @@ processed_field: return(false); } -/** Convert field type and length to InnoDB format */ -static void get_type(const Field& f, uint& prtype, uint8_t& mtype, - uint16_t& len) -{ - mtype = get_innobase_type_from_mysql_type(&prtype, &f); - len = static_cast(f.pack_length()); - prtype |= f.type(); - if (f.type() == MYSQL_TYPE_VARCHAR) { - auto l = static_cast(f).length_bytes; - len = static_cast(len - l); - if (l == 2) prtype |= DATA_LONG_TRUE_VARCHAR; - } - if (!f.real_maybe_null()) prtype |= DATA_NOT_NULL; - if (f.binary()) prtype |= DATA_BINARY_TYPE; - if (f.table->versioned()) { - if (&f == f.table->field[f.table->s->vers.start_fieldno]) { - prtype |= DATA_VERS_START; - } else if (&f == f.table->field[f.table->s->vers.end_fieldno]) { - prtype |= DATA_VERS_END; - } else if (!(f.flags & VERS_UPDATE_UNVERSIONED_FLAG)) { - prtype |= DATA_VERSIONED; - } - } - if (!f.stored_in_db()) prtype |= DATA_VIRTUAL; - - if (dtype_is_string_type(mtype)) { - prtype |= f.charset()->number << 16; - } -} - /** Enlarge a column in the data dictionary tables. @param ctx In-place ALTER TABLE context @param trx data dictionary transaction @@ -10617,6 +10701,7 @@ commit_cache_norebuild( DBUG_ASSERT(dict_index_get_online_status(index) == ONLINE_INDEX_COMPLETE); DBUG_ASSERT(!index->is_committed()); + index->change_col_info = nullptr; index->set_committed(true); } @@ -11368,7 +11453,8 @@ foreign_fail: || ha_alter_info->alter_info->create_list.elements)) || (ctx0->is_instant() && m_prebuilt->table->n_v_cols - && ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) { + && ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER) + || !ctx0->change_col_collate.empty()) { DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1); ut_ad(ctx0->prebuilt == m_prebuilt); diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index c2b8c3e00b6..5eaad5bf552 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, 2020 MariaDB Corporation. +Copyright (c) 2017, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -581,6 +581,10 @@ struct dtuple_t { /** @return whether this is a hidden metadata record for instant ADD COLUMN or ALTER TABLE */ bool is_metadata() const { return is_metadata(info_bits); } + + /** Copy type information from index fields. + @param index index field to be copied */ + inline void copy_field_types(const dict_index_t &index); }; inline ulint dtuple_get_n_fields(const dtuple_t* tuple) diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index ae688bf85fe..3d63ddb767c 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -488,6 +488,8 @@ dtype_print( const dtype_t* type); #endif /* UNIV_DEBUG */ +struct dict_col_t; + /* Structure for an SQL data type. If you add fields to this structure, be sure to initialize them everywhere. This structure is initialized in the following functions: @@ -543,6 +545,10 @@ struct dtype_t{ mbminlen = 0; mbmaxlen = 0; } + + /** Copy the type information from a column. + @param col column type to be copied */ + void assign(const dict_col_t &col); }; /** The DB_TRX_ID,DB_ROLL_PTR values for "no history is available" */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index da96d07e260..bd8872019cb 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -966,6 +966,26 @@ const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX"; /** Data structure for an index. Most fields will be initialized to 0, NULL or FALSE in dict_mem_index_create(). */ struct dict_index_t { + /** Columns whose character-set collation is being changed */ + struct col_info + { + /** number of columns whose charset-collation is being changed */ + unsigned n_cols; + /** columns with changed charset-collation */ + dict_col_t *cols; + + /** Add a column with changed collation. */ + dict_col_t *add(mem_heap_t *heap, const dict_col_t &col, unsigned offset) + { + ut_ad(offset < n_cols); + if (!cols) + cols= static_cast + (mem_heap_alloc(heap, n_cols * sizeof col)); + new (&cols[offset]) dict_col_t(col); + return &cols[offset]; + } + }; + /** Maximum number of fields */ static constexpr unsigned MAX_N_FIELDS= (1U << 10) - 1; @@ -1051,6 +1071,16 @@ struct dict_index_t { It should use heap from dict_index_t. It should be freed while removing the index from table. */ dict_add_v_col_info* new_vcol_info; + + /** During ALTER TABLE, columns that a being-added index depends on + and whose encoding or collation is being changed to something + that is compatible with the clustered index. + Allocated from dict_index_t::heap. + + @see rollback_inplace_alter_table() + @see ha_innobase_inplace_ctx::col_collations */ + col_info* change_col_info; + UT_LIST_NODE_T(dict_index_t) indexes;/*!< list of indexes of the table */ #ifdef BTR_CUR_ADAPT @@ -1145,6 +1175,7 @@ public: { ut_ad(!to_be_dropped); ut_ad(committed || !(type & DICT_CLUSTERED)); + ut_ad(!committed || !change_col_info); uncommitted = !committed; } @@ -1310,6 +1341,16 @@ public: ulint get_new_n_vcol() const { return new_vcol_info ? new_vcol_info->n_v_col : 0; } + /** Assign the number of collation change fields as a part of the index + @param n_cols number of columns whose collation is changing */ + void init_change_cols(unsigned n_cols) + { + ut_ad(n_fields > n_cols); + change_col_info= static_cast + (mem_heap_zalloc(heap, sizeof(col_info))); + change_col_info->n_cols= n_cols; + } + /** Reconstruct the clustered index fields. @return whether metadata is incorrect */ inline bool reconstruct_fields(); diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h index e9e250435f0..52096d48313 100644 --- a/storage/innobase/include/row0merge.h +++ b/storage/innobase/include/row0merge.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2021, MariaDB Corporation. +Copyright (c) 2015, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -216,6 +216,11 @@ row_merge_is_index_usable( const dict_index_t* index) /*!< in: index to check */ MY_ATTRIBUTE((nonnull, warn_unused_result)); +/** Map from column numbers to column definitions that include +changes to the collation, when the encoding is compatible with +the original column and no table rebuild is needed */ +typedef std::map col_collations; + /** Build indexes on a table by reading a clustered index, creating a temporary file containing index entries, merge sorting these index entries and inserting sorted index entries to indexes. @@ -244,6 +249,7 @@ this function and it will be passed to other functions for further accounting. @param[in] eval_table mysql table used to evaluate virtual column value, see innobase_get_computed_value(). @param[in] allow_non_null allow the conversion from null to not-null +@param[in] col_collate columns whose collations changed, or nullptr @return DB_SUCCESS or error code */ dberr_t row_merge_build_indexes( @@ -263,7 +269,8 @@ row_merge_build_indexes( ut_stage_alter_t* stage, const dict_add_v_col_t* add_v, struct TABLE* eval_table, - bool allow_non_null) + bool allow_non_null, + const col_collations* col_collate) MY_ATTRIBUTE((warn_unused_result)); /********************************************************************//** diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 28f0eb42825..eeac4b1712e 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -3877,6 +3877,23 @@ static void row_log_mark_other_online_index_abort(dict_table_t *table) table->drop_aborted= TRUE; } +void dtype_t::assign(const dict_col_t &col) +{ + prtype= col.prtype; + mtype= col.mtype; + len= col.len; + mbminlen= col.mbminlen; + mbmaxlen= col.mbmaxlen; +} + +inline void dtuple_t::copy_field_types(const dict_index_t &index) +{ + ut_ad(index.n_fields == n_fields); + if (UNIV_LIKELY_NULL(index.change_col_info)) + for (ulint i= 0; i < n_fields; i++) + fields[i].type.assign(*index.fields[i].col); +} + void UndorecApplier::log_insert(const dtuple_t &tuple, dict_index_t *clust_index) { @@ -3943,7 +3960,8 @@ void UndorecApplier::log_insert(const dtuple_t &tuple, { dtuple_t *entry= row_build_index_entry_low(row, ext, index, heap, ROW_BUILD_NORMAL); - success= row_log_online_op(index, entry, trx_id); + entry->copy_field_types(*index); + success= row_log_online_op(index, entry, trx_id); } index->lock.s_unlock(); @@ -4069,11 +4087,15 @@ void UndorecApplier::log_update(const dtuple_t &tuple, dtuple_t *old_entry= row_build_index_entry_low( old_row, old_ext, index, heap, ROW_BUILD_NORMAL); - success= row_log_online_op(index, old_entry, 0); + old_entry->copy_field_types(*index); + + success= row_log_online_op(index, old_entry, 0); dtuple_t *new_entry= row_build_index_entry_low( row, new_ext, index, heap, ROW_BUILD_NORMAL); + new_entry->copy_field_types(*index); + if (success) success= row_log_online_op(index, new_entry, trx_id); } @@ -4082,6 +4104,8 @@ void UndorecApplier::log_update(const dtuple_t &tuple, dtuple_t *old_entry= row_build_index_entry_low( row, new_ext, index, heap, ROW_BUILD_NORMAL); + old_entry->copy_field_types(*index); + success= row_log_online_op(index, old_entry, 0); } } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index c0870698c5b..60e9c1915e9 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -490,6 +490,7 @@ row_merge_buf_redundant_convert( @param[in,out] v_heap heap memory to process data for virtual column @param[in,out] my_table mysql table object @param[in] trx transaction object +@param[in] col_collate columns whose collations changed, or nullptr @return number of rows added, 0 if out of space */ static ulint @@ -506,7 +507,8 @@ row_merge_buf_add( dberr_t* err, mem_heap_t** v_heap, TABLE* my_table, - trx_t* trx) + trx_t* trx, + const col_collations* col_collate) { ulint i; const dict_index_t* index; @@ -520,6 +522,7 @@ row_merge_buf_add( doc_id_t write_doc_id; ulint n_row_added = 0; VCOL_STORAGE vcol_storage; + DBUG_ENTER("row_merge_buf_add"); if (buf->n_tuples >= buf->max_tuples) { @@ -611,8 +614,17 @@ error: row_field = dtuple_get_nth_field(row, col->ind); dfield_copy(field, row_field); - } + /* Copy the column collation to the + tuple field */ + if (col_collate) { + auto it = col_collate->find(col->ind); + if (it != col_collate->end()) { + field->type + .assign(*it->second); + } + } + } /* Tokenize and process data for FTS */ if (index->type & DICT_FTS) { @@ -1657,6 +1669,7 @@ stage->inc() will be called for each page read. @param[in] eval_table mysql table used to evaluate virtual column value, see innobase_get_computed_value(). @param[in] allow_not_null allow null to not-null conversion +@param[in] col_collate columns whose collations changed, or nullptr @return DB_SUCCESS or error */ static MY_ATTRIBUTE((warn_unused_result)) dberr_t @@ -1684,7 +1697,8 @@ row_merge_read_clustered_index( double pct_cost, row_merge_block_t* crypt_block, struct TABLE* eval_table, - bool allow_not_null) + bool allow_not_null, + const col_collations* col_collate) { dict_index_t* clust_index; /* Clustered index */ mem_heap_t* row_heap = NULL;/* Heap memory to create @@ -2391,7 +2405,8 @@ write_buffers: buf, fts_index, old_table, new_table, psort_info, row, ext, &doc_id, conv_heap, &err, - &v_heap, eval_table, trx)))) { + &v_heap, eval_table, trx, + col_collate)))) { /* If we are creating FTS index, a single row can generate more @@ -2718,7 +2733,8 @@ write_buffers: buf, fts_index, old_table, new_table, psort_info, row, ext, &doc_id, conv_heap, - &err, &v_heap, eval_table, trx)))) { + &err, &v_heap, eval_table, + trx, col_collate)))) { /* An empty buffer should have enough room for at least one record. */ ut_ad(err == DB_COMPUTE_VALUE_FAILED @@ -4422,6 +4438,7 @@ this function and it will be passed to other functions for further accounting. @param[in] eval_table mysql table used to evaluate virtual column value, see innobase_get_computed_value(). @param[in] allow_not_null allow the conversion from null to not-null +@param[in] col_collate columns whose collations changed, or nullptr @return DB_SUCCESS or error code */ dberr_t row_merge_build_indexes( @@ -4441,7 +4458,8 @@ row_merge_build_indexes( ut_stage_alter_t* stage, const dict_add_v_col_t* add_v, struct TABLE* eval_table, - bool allow_not_null) + bool allow_not_null, + const col_collations* col_collate) { merge_file_t* merge_files; row_merge_block_t* block; @@ -4591,7 +4609,8 @@ row_merge_build_indexes( fts_sort_idx, psort_info, merge_files, key_numbers, n_indexes, defaults, add_v, col_map, add_autoinc, sequence, block, skip_pk_sort, &tmpfd, stage, - pct_cost, crypt_block, eval_table, allow_not_null); + pct_cost, crypt_block, eval_table, allow_not_null, + col_collate); stage->end_phase_read_pk(); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 84f2b54f517..0c9ad03cc93 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -823,6 +823,10 @@ row_create_prebuilt( DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value", ut_a(temp_index->n_user_defined_cols == MAX_REF_PARTS);); + if (temp_index->is_corrupted()) { + continue; + } + uint temp_len = 0; for (uint i = 0; i < temp_index->n_uniq; i++) { ulint type = temp_index->fields[i].col->mtype;