mirror of
https://github.com/MariaDB/server.git
synced 2025-07-11 15:22:09 +03:00
A joint patch for MDEV-19284 and MDEV-19285 (INSTANT ALTER)
This patch fixes: - MDEV-19284 INSTANT ALTER with ucs2-to-utf16 conversion produces bad data - MDEV-19285 INSTANT ALTER from ascii_general_ci to latin1_general_ci produces corrupt data These regressions were introduced in 10.4.3 by: - MDEV-15564 Avoid table rebuild in ALTER TABLE on collation or charset changes Changes: 1. Cleanup: Adding a helper method Field_longstr::csinfo_change_allows_instant_alter(), to remove some duplicate code in field.cc. 2. Cleanup: removing Type_handler::Charsets_are_compatible() and static function charsets_are_compatible() and introducing new methods in the recently added class Charset instead: - encoding_allows_reinterpret_as() - encoding_and_order_allow_reinterpret_as() 3. Bug fix: Removing the code that allowed instant conversion for ascii-to->8bit and ucs2-to->utf16. This actually fixes MDEV-19284 and MDEV-19285. 4. Bug fix: Adding a helper method Charset::collation_specific_name(). The old corresponding code in Type_handler::Charsets_are_compatible() was not safe against (badly named) user-defined collations whose character set name can be longer than collation name.
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
--- instant_alter_charset.result
|
--- instant_alter_charset.result 2019-04-23 17:42:23.324326518 +0400
|
||||||
+++ instant_alter_charset,redundant.result
|
+++ instant_alter_charset,redundant.result 2019-04-23 17:42:46.047531591 +0400
|
||||||
@@ -254,7 +254,6 @@
|
@@ -279,7 +279,6 @@
|
||||||
alter table boundary_255
|
alter table boundary_255
|
||||||
modify b varchar(200) charset utf8mb3,
|
modify a varchar(70) charset utf8mb4,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY
|
-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY
|
||||||
alter table boundary_255
|
drop table boundary_255;
|
||||||
modify c varchar(300) charset utf8mb3,
|
create table fully_compatible (
|
||||||
algorithm=instant;
|
id int auto_increment unique key,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,9 +20,13 @@ select c.prtype, c.len from information_schema.innodb_sys_columns as c inner joi
|
|||||||
alter table no_rebuild
|
alter table no_rebuild
|
||||||
change a a char(150) charset utf8mb3 collate utf8mb3_spanish_ci,
|
change a a char(150) charset utf8mb3 collate utf8mb3_spanish_ci,
|
||||||
algorithm=inplace;
|
algorithm=inplace;
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
alter table rebuild
|
alter table rebuild
|
||||||
change a a varchar(150) charset latin1 not null default 'asdf',
|
change a a varchar(150) charset latin1 not null default 'asdf',
|
||||||
algorithm=inplace;
|
algorithm=inplace;
|
||||||
|
alter table rebuild
|
||||||
|
change a a varchar(150) charset latin1 not null default 'asdf',
|
||||||
|
algorithm=copy;
|
||||||
select name, prtype, len from information_schema.innodb_sys_columns
|
select name, prtype, len from information_schema.innodb_sys_columns
|
||||||
where table_id = @id;
|
where table_id = @id;
|
||||||
select c.prtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id
|
select c.prtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id
|
||||||
@ -41,7 +45,7 @@ create table supported_types (
|
|||||||
) engine=innodb;
|
) engine=innodb;
|
||||||
|
|
||||||
alter table supported_types
|
alter table supported_types
|
||||||
convert to charset latin1,
|
convert to charset ascii collate ascii_bin,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
|
|
||||||
drop table supported_types;
|
drop table supported_types;
|
||||||
@ -53,7 +57,7 @@ create table various_cases (
|
|||||||
) engine=innodb;
|
) engine=innodb;
|
||||||
|
|
||||||
alter table various_cases
|
alter table various_cases
|
||||||
change a a char(150) charset latin1,
|
change a a char(150) charset ascii collate ascii_bin,
|
||||||
algorithm=inplace;
|
algorithm=inplace;
|
||||||
|
|
||||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
@ -88,7 +92,7 @@ create table all_texts (
|
|||||||
) engine=innodb;
|
) engine=innodb;
|
||||||
|
|
||||||
alter table all_texts
|
alter table all_texts
|
||||||
convert to charset latin1 collate latin1_general_ci,
|
convert to charset ascii collate ascii_bin,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
|
|
||||||
drop table all_texts;
|
drop table all_texts;
|
||||||
@ -244,10 +248,15 @@ alter table latin1_swedish_special_case
|
|||||||
modify copy1 varchar(150) charset latin1 collate latin1_swedish_ci,
|
modify copy1 varchar(150) charset latin1 collate latin1_swedish_ci,
|
||||||
modify copy2 char(150) charset latin1 collate latin1_swedish_ci,
|
modify copy2 char(150) charset latin1 collate latin1_swedish_ci,
|
||||||
algorithm=copy;
|
algorithm=copy;
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
alter table latin1_swedish_special_case
|
alter table latin1_swedish_special_case
|
||||||
modify instant1 varchar(150) charset latin1 collate latin1_swedish_ci,
|
modify instant1 varchar(150) charset latin1 collate latin1_swedish_ci,
|
||||||
modify instant2 char(150) charset latin1 collate latin1_swedish_ci,
|
modify instant2 char(150) charset latin1 collate latin1_swedish_ci,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
|
alter table latin1_swedish_special_case
|
||||||
|
modify instant1 varchar(150) charset latin1 collate latin1_swedish_ci,
|
||||||
|
modify instant2 char(150) charset latin1 collate latin1_swedish_ci,
|
||||||
|
algorithm=copy;
|
||||||
select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id
|
select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id
|
||||||
where t.name = 'test/latin1_swedish_special_case';
|
where t.name = 'test/latin1_swedish_special_case';
|
||||||
alter table latin1_swedish_special_case
|
alter table latin1_swedish_special_case
|
||||||
@ -275,26 +284,42 @@ create table boundary_255 (
|
|||||||
c varchar(300) charset ascii
|
c varchar(300) charset ascii
|
||||||
) engine=innodb;
|
) engine=innodb;
|
||||||
|
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
alter table boundary_255
|
alter table boundary_255
|
||||||
modify a varchar(50) charset utf8mb3,
|
modify a varchar(50) charset utf8mb3,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
|
alter table boundary_255
|
||||||
|
modify a varchar(50) charset utf8mb3,
|
||||||
|
algorithm=copy;
|
||||||
|
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
|
alter table boundary_255
|
||||||
|
modify b varchar(200) charset utf8mb3,
|
||||||
|
algorithm=instant;
|
||||||
|
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
|
alter table boundary_255
|
||||||
|
modify c varchar(300) charset utf8mb3,
|
||||||
|
algorithm=instant;
|
||||||
|
|
||||||
|
drop table boundary_255;
|
||||||
|
|
||||||
|
create table boundary_255 (
|
||||||
|
a varchar(70) charset utf8mb3
|
||||||
|
) engine=innodb;
|
||||||
|
|
||||||
if ($row_format == 'redundant') {
|
if ($row_format == 'redundant') {
|
||||||
alter table boundary_255
|
alter table boundary_255
|
||||||
modify b varchar(200) charset utf8mb3,
|
modify a varchar(70) charset utf8mb4,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
}
|
}
|
||||||
if ($row_format != 'redundant') {
|
if ($row_format != 'redundant') {
|
||||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
alter table boundary_255
|
alter table boundary_255
|
||||||
modify b varchar(200) charset utf8mb3,
|
modify a varchar(70) charset utf8mb4,
|
||||||
algorithm=instant;
|
algorithm=instant;
|
||||||
}
|
}
|
||||||
|
|
||||||
alter table boundary_255
|
|
||||||
modify c varchar(300) charset utf8mb3,
|
|
||||||
algorithm=instant;
|
|
||||||
|
|
||||||
drop table boundary_255;
|
drop table boundary_255;
|
||||||
|
|
||||||
create table fully_compatible (
|
create table fully_compatible (
|
||||||
@ -338,30 +363,7 @@ insert into fully_compatible (from_charset, from_collate, to_charset, to_collate
|
|||||||
('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_general_nopad_ci'),
|
('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_general_nopad_ci'),
|
||||||
('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_nopad_bin'),
|
('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_nopad_bin'),
|
||||||
('utf8mb3', 'utf8mb3_unicode_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_nopad_ci'),
|
('utf8mb3', 'utf8mb3_unicode_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_nopad_ci'),
|
||||||
('utf8mb3', 'utf8mb3_unicode_520_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_520_nopad_ci'),
|
('utf8mb3', 'utf8mb3_unicode_520_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_520_nopad_ci')
|
||||||
|
|
||||||
('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'),
|
|
||||||
('ucs2', 'ucs2_unicode_ci', 'utf16', 'utf16_unicode_ci'),
|
|
||||||
('ucs2', 'ucs2_icelandic_ci', 'utf16', 'utf16_icelandic_ci'),
|
|
||||||
('ucs2', 'ucs2_latvian_ci', 'utf16', 'utf16_latvian_ci'),
|
|
||||||
('ucs2', 'ucs2_romanian_ci', 'utf16', 'utf16_romanian_ci'),
|
|
||||||
('ucs2', 'ucs2_slovenian_ci', 'utf16', 'utf16_slovenian_ci'),
|
|
||||||
('ucs2', 'ucs2_polish_ci', 'utf16', 'utf16_polish_ci'),
|
|
||||||
('ucs2', 'ucs2_estonian_ci', 'utf16', 'utf16_estonian_ci'),
|
|
||||||
('ucs2', 'ucs2_spanish_ci', 'utf16', 'utf16_spanish_ci'),
|
|
||||||
('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'),
|
|
||||||
|
|
||||||
('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_general_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_general_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'latin1', 'latin1_general_ci'),
|
|
||||||
('ascii', 'ascii_bin', 'latin1', 'latin1_bin'),
|
|
||||||
('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_nopad_bin'),
|
|
||||||
('ascii', 'ascii_general_ci', 'latin2', 'latin2_general_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'latin7', 'latin7_general_ci'),
|
|
||||||
('ascii', 'ascii_bin', 'koi8u', 'koi8u_bin'),
|
|
||||||
('ascii', 'ascii_bin', 'ujis', 'ujis_bin'),
|
|
||||||
('ascii', 'ascii_bin', 'big5', 'big5_bin'),
|
|
||||||
('ascii', 'ascii_bin', 'gbk', 'gbk_bin')
|
|
||||||
;
|
;
|
||||||
|
|
||||||
let $data_size = `select count(*) from fully_compatible`;
|
let $data_size = `select count(*) from fully_compatible`;
|
||||||
@ -404,47 +406,19 @@ create table compatible_without_index (
|
|||||||
);
|
);
|
||||||
|
|
||||||
insert into compatible_without_index (from_charset, from_collate, to_charset, to_collate) values
|
insert into compatible_without_index (from_charset, from_collate, to_charset, to_collate) values
|
||||||
('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
|
||||||
('ascii', 'ascii_bin', 'latin1', 'latin1_swedish_ci'),
|
|
||||||
('ascii', 'ascii_general_nopad_ci', 'latin1', 'latin1_swedish_ci'),
|
|
||||||
('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_swedish_ci'),
|
|
||||||
|
|
||||||
('ascii', 'ascii_general_ci', 'koi8u', 'koi8u_bin'),
|
|
||||||
('ascii', 'ascii_general_nopad_ci', 'koi8u', 'koi8u_bin'),
|
|
||||||
('ascii', 'ascii_nopad_bin', 'koi8u', 'koi8u_bin'),
|
|
||||||
|
|
||||||
('ascii', 'ascii_general_ci', 'latin1', 'latin1_swedish_ci'),
|
|
||||||
('ascii', 'ascii_bin', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
|
||||||
('ascii', 'ascii_general_nopad_ci', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
|
||||||
('ascii', 'ascii_nopad_bin', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
|
||||||
|
|
||||||
('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_danish_ci'),
|
|
||||||
('ascii', 'ascii_bin', 'utf8mb4', 'utf8mb4_danish_ci'),
|
|
||||||
('ascii', 'ascii_general_nopad_ci', 'utf8mb4', 'utf8mb4_danish_ci'),
|
|
||||||
('ascii', 'ascii_nopad_bin', 'utf8mb4', 'utf8mb4_danish_ci'),
|
|
||||||
|
|
||||||
('utf8mb3', 'utf8mb3_general_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
('utf8mb3', 'utf8mb3_general_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
||||||
('utf8mb3', 'utf8mb3_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
('utf8mb3', 'utf8mb3_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
||||||
('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
||||||
('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'),
|
||||||
|
|
||||||
('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_nopad_ci'),
|
|
||||||
|
|
||||||
('ucs2', 'ucs2_myanmar_ci', 'utf16', 'utf16_thai_520_w2'),
|
|
||||||
('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_unicode_nopad_ci'),
|
|
||||||
('ucs2', 'ucs2_general_mysql500_ci', 'utf16', 'utf16_spanish2_ci'),
|
|
||||||
|
|
||||||
('ascii', 'ascii_general_ci', 'ascii', 'ascii_bin'),
|
('ascii', 'ascii_general_ci', 'ascii', 'ascii_bin'),
|
||||||
('utf8mb3', 'utf8mb3_roman_ci', 'utf8mb3', 'utf8mb3_lithuanian_ci'),
|
('utf8mb3', 'utf8mb3_roman_ci', 'utf8mb3', 'utf8mb3_lithuanian_ci'),
|
||||||
('utf8mb4', 'utf8mb4_thai_520_w2', 'utf8mb4', 'utf8mb4_persian_ci'),
|
('utf8mb4', 'utf8mb4_thai_520_w2', 'utf8mb4', 'utf8mb4_persian_ci'),
|
||||||
('utf8mb3', 'utf8mb3_myanmar_ci', 'utf8mb4', 'utf8mb4_german2_ci'),
|
('utf8mb3', 'utf8mb3_myanmar_ci', 'utf8mb4', 'utf8mb4_german2_ci'),
|
||||||
('utf8mb3', 'utf8mb3_general_ci', 'utf8mb3', 'utf8mb3_unicode_ci'),
|
('utf8mb3', 'utf8mb3_general_ci', 'utf8mb3', 'utf8mb3_unicode_ci'),
|
||||||
('latin1', 'latin1_general_cs', 'latin1', 'latin1_general_ci'),
|
('latin1', 'latin1_general_cs', 'latin1', 'latin1_general_ci'),
|
||||||
('ascii', 'ascii_general_ci', 'ujis', 'ujis_japanese_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'big5', 'big5_chinese_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'latin2', 'latin2_croatian_ci'),
|
|
||||||
('ascii', 'ascii_general_ci', 'latin7', 'latin7_estonian_cs'),
|
|
||||||
('utf16', 'utf16_general_ci', 'utf16', 'utf16_german2_ci')
|
('utf16', 'utf16_general_ci', 'utf16', 'utf16_german2_ci')
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -494,6 +468,59 @@ create table fully_incompatible (
|
|||||||
);
|
);
|
||||||
|
|
||||||
insert into fully_incompatible (from_charset, from_collate, to_charset, to_collate) values
|
insert into fully_incompatible (from_charset, from_collate, to_charset, to_collate) values
|
||||||
|
('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_general_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_general_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'latin1', 'latin1_general_ci'),
|
||||||
|
('ascii', 'ascii_bin', 'latin1', 'latin1_bin'),
|
||||||
|
('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_nopad_bin'),
|
||||||
|
('ascii', 'ascii_general_ci', 'latin2', 'latin2_general_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'latin7', 'latin7_general_ci'),
|
||||||
|
('ascii', 'ascii_bin', 'koi8u', 'koi8u_bin'),
|
||||||
|
('ascii', 'ascii_bin', 'ujis', 'ujis_bin'),
|
||||||
|
('ascii', 'ascii_bin', 'big5', 'big5_bin'),
|
||||||
|
('ascii', 'ascii_bin', 'gbk', 'gbk_bin'),
|
||||||
|
|
||||||
|
('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
||||||
|
('ascii', 'ascii_bin', 'latin1', 'latin1_swedish_ci'),
|
||||||
|
('ascii', 'ascii_general_nopad_ci', 'latin1', 'latin1_swedish_ci'),
|
||||||
|
('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_swedish_ci'),
|
||||||
|
|
||||||
|
('ascii', 'ascii_general_ci', 'koi8u', 'koi8u_bin'),
|
||||||
|
('ascii', 'ascii_general_nopad_ci', 'koi8u', 'koi8u_bin'),
|
||||||
|
('ascii', 'ascii_nopad_bin', 'koi8u', 'koi8u_bin'),
|
||||||
|
|
||||||
|
('ascii', 'ascii_general_ci', 'latin1', 'latin1_swedish_ci'),
|
||||||
|
('ascii', 'ascii_bin', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
||||||
|
('ascii', 'ascii_general_nopad_ci', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
||||||
|
('ascii', 'ascii_nopad_bin', 'utf8mb3', 'utf8mb3_swedish_ci'),
|
||||||
|
|
||||||
|
('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_danish_ci'),
|
||||||
|
('ascii', 'ascii_bin', 'utf8mb4', 'utf8mb4_danish_ci'),
|
||||||
|
('ascii', 'ascii_general_nopad_ci', 'utf8mb4', 'utf8mb4_danish_ci'),
|
||||||
|
('ascii', 'ascii_nopad_bin', 'utf8mb4', 'utf8mb4_danish_ci'),
|
||||||
|
|
||||||
|
('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_nopad_ci'),
|
||||||
|
|
||||||
|
('ascii', 'ascii_general_ci', 'ujis', 'ujis_japanese_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'big5', 'big5_chinese_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'latin2', 'latin2_croatian_ci'),
|
||||||
|
('ascii', 'ascii_general_ci', 'latin7', 'latin7_estonian_cs'),
|
||||||
|
|
||||||
|
('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'),
|
||||||
|
('ucs2', 'ucs2_unicode_ci', 'utf16', 'utf16_unicode_ci'),
|
||||||
|
('ucs2', 'ucs2_icelandic_ci', 'utf16', 'utf16_icelandic_ci'),
|
||||||
|
('ucs2', 'ucs2_latvian_ci', 'utf16', 'utf16_latvian_ci'),
|
||||||
|
('ucs2', 'ucs2_romanian_ci', 'utf16', 'utf16_romanian_ci'),
|
||||||
|
('ucs2', 'ucs2_slovenian_ci', 'utf16', 'utf16_slovenian_ci'),
|
||||||
|
('ucs2', 'ucs2_polish_ci', 'utf16', 'utf16_polish_ci'),
|
||||||
|
('ucs2', 'ucs2_estonian_ci', 'utf16', 'utf16_estonian_ci'),
|
||||||
|
('ucs2', 'ucs2_spanish_ci', 'utf16', 'utf16_spanish_ci'),
|
||||||
|
('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'),
|
||||||
|
('ucs2', 'ucs2_myanmar_ci', 'utf16', 'utf16_thai_520_w2'),
|
||||||
|
('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_unicode_nopad_ci'),
|
||||||
|
('ucs2', 'ucs2_general_mysql500_ci', 'utf16', 'utf16_spanish2_ci'),
|
||||||
|
|
||||||
('utf8mb4', 'utf8mb4_general_ci', 'utf8mb3', 'utf8mb3_general_ci'),
|
('utf8mb4', 'utf8mb4_general_ci', 'utf8mb3', 'utf8mb3_general_ci'),
|
||||||
('utf8mb4', 'utf8mb4_general_ci', 'ascii', 'ascii_general_ci'),
|
('utf8mb4', 'utf8mb4_general_ci', 'ascii', 'ascii_general_ci'),
|
||||||
('utf8mb3', 'utf8mb3_general_ci', 'ascii', 'ascii_general_ci'),
|
('utf8mb3', 'utf8mb3_general_ci', 'ascii', 'ascii_general_ci'),
|
||||||
@ -536,3 +563,33 @@ while ($counter <= $data_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drop table fully_incompatible;
|
drop table fully_incompatible;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19284 INSTANT ALTER with ucs2-to-utf16 conversion produces bad data
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2, PRIMARY KEY(a)) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES ('a'),(0xD800);
|
||||||
|
--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
|
||||||
|
ALTER TABLE t1 ALGORITHM=COPY, MODIFY a VARCHAR(10) CHARACTER SET utf16;
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
|
ALTER TABLE t1 ALGORITHM=INSTANT, MODIFY a VARCHAR(10) CHARACTER SET utf16;
|
||||||
|
--enable_info ONCE
|
||||||
|
ALTER IGNORE TABLE t1 MODIFY a VARCHAR(10) CHARACTER SET utf16;
|
||||||
|
SELECT HEX(a) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19285 INSTANT ALTER from ascii_general_ci to latin1_general_ci produces currupt data
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ascii COLLATE ascii_general_ci, PRIMARY KEY(a)) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES ('a'),(0xC0),('b');
|
||||||
|
--error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
|
||||||
|
ALTER TABLE t1 ALGORITHM=COPY, MODIFY a VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci;
|
||||||
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||||
|
ALTER TABLE t1 ALGORITHM=INSTANT, MODIFY a VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci;
|
||||||
|
--enable_info ONCE
|
||||||
|
ALTER IGNORE TABLE t1 MODIFY a VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci;
|
||||||
|
SELECT HEX(a) FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
25
sql/field.cc
25
sql/field.cc
@ -7092,6 +7092,17 @@ int Field_str::store(double nr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Field_longstr::
|
||||||
|
csinfo_change_allows_instant_alter(const Create_field *to) const
|
||||||
|
{
|
||||||
|
Charset cs(field_charset);
|
||||||
|
const bool part_of_a_key= !to->field->part_of_key.is_clear_all();
|
||||||
|
return part_of_a_key ?
|
||||||
|
cs.encoding_and_order_allow_reinterpret_as(to->charset) :
|
||||||
|
cs.encoding_allows_reinterpret_as(to->charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_string::is_equal(Create_field *new_field)
|
uint Field_string::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(!compression_method());
|
DBUG_ASSERT(!compression_method());
|
||||||
@ -7102,9 +7113,7 @@ uint Field_string::is_equal(Create_field *new_field)
|
|||||||
if (new_field->char_length < char_length())
|
if (new_field->char_length < char_length())
|
||||||
return IS_EQUAL_NO;
|
return IS_EQUAL_NO;
|
||||||
|
|
||||||
const bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
if (!csinfo_change_allows_instant_alter(new_field))
|
||||||
if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset,
|
|
||||||
part_of_a_key))
|
|
||||||
return IS_EQUAL_NO;
|
return IS_EQUAL_NO;
|
||||||
|
|
||||||
if (new_field->length == max_display_length())
|
if (new_field->length == max_display_length())
|
||||||
@ -7954,9 +7963,7 @@ uint Field_varstring::is_equal(Create_field *new_field)
|
|||||||
if (!new_field->compression_method() != !compression_method())
|
if (!new_field->compression_method() != !compression_method())
|
||||||
return IS_EQUAL_NO;
|
return IS_EQUAL_NO;
|
||||||
|
|
||||||
bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
if (!csinfo_change_allows_instant_alter(new_field))
|
||||||
if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset,
|
|
||||||
part_of_a_key))
|
|
||||||
return IS_EQUAL_NO;
|
return IS_EQUAL_NO;
|
||||||
|
|
||||||
const Type_handler *new_type_handler= new_field->type_handler();
|
const Type_handler *new_type_handler= new_field->type_handler();
|
||||||
@ -8751,12 +8758,8 @@ uint Field_blob::is_equal(Create_field *new_field)
|
|||||||
return IS_EQUAL_NO;
|
return IS_EQUAL_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
if (!csinfo_change_allows_instant_alter(new_field))
|
||||||
if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset,
|
|
||||||
part_of_a_key))
|
|
||||||
{
|
|
||||||
return IS_EQUAL_NO;
|
return IS_EQUAL_NO;
|
||||||
}
|
|
||||||
|
|
||||||
if (field_charset != new_field->charset)
|
if (field_charset != new_field->charset)
|
||||||
{
|
{
|
||||||
|
@ -1926,6 +1926,7 @@ protected:
|
|||||||
CHARSET_INFO *cs, size_t nchars);
|
CHARSET_INFO *cs, size_t nchars);
|
||||||
String *uncompress(String *val_buffer, String *val_ptr,
|
String *uncompress(String *val_buffer, String *val_ptr,
|
||||||
const uchar *from, uint from_length);
|
const uchar *from, uint from_length);
|
||||||
|
bool csinfo_change_allows_instant_alter(const Create_field *to) const;
|
||||||
public:
|
public:
|
||||||
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||||
uchar null_bit_arg, utype unireg_check_arg,
|
uchar null_bit_arg, utype unireg_check_arg,
|
||||||
|
@ -159,6 +159,14 @@ public:
|
|||||||
{
|
{
|
||||||
swap_variables(CHARSET_INFO*, m_charset, other.m_charset);
|
swap_variables(CHARSET_INFO*, m_charset, other.m_charset);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Collation name without the character set name.
|
||||||
|
For example, in case of "latin1_swedish_ci",
|
||||||
|
this method returns "_swedish_ci".
|
||||||
|
*/
|
||||||
|
LEX_CSTRING collation_specific_name() const;
|
||||||
|
bool encoding_allows_reinterpret_as(CHARSET_INFO *cs) const;
|
||||||
|
bool encoding_and_order_allow_reinterpret_as(CHARSET_INFO *cs) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -8219,48 +8219,51 @@ Type_handler_timestamp_common::Item_param_val_native(THD *thd,
|
|||||||
TIME_to_native(thd, <ime, to, item->datetime_precision(thd));
|
TIME_to_native(thd, <ime, to, item->datetime_precision(thd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool charsets_are_compatible(const char *old_cs_name,
|
|
||||||
const CHARSET_INFO *new_ci)
|
LEX_CSTRING Charset::collation_specific_name() const
|
||||||
{
|
{
|
||||||
const char *new_cs_name= new_ci->csname;
|
/*
|
||||||
|
User defined collations can provide arbitrary names
|
||||||
|
for character sets and collations, so a collation
|
||||||
|
name not necessarily starts with the character set name.
|
||||||
|
*/
|
||||||
|
size_t csname_length= strlen(m_charset->csname);
|
||||||
|
if (strncmp(m_charset->name, m_charset->csname, csname_length))
|
||||||
|
return {NULL, 0};
|
||||||
|
const char *ptr= m_charset->name + csname_length;
|
||||||
|
return {ptr, strlen(ptr) };
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(old_cs_name, new_cs_name))
|
|
||||||
|
bool
|
||||||
|
Charset::encoding_allows_reinterpret_as(const CHARSET_INFO *cs) const
|
||||||
|
{
|
||||||
|
if (!strcmp(m_charset->csname, cs->csname))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!strcmp(old_cs_name, MY_UTF8MB3) && !strcmp(new_cs_name, MY_UTF8MB4))
|
if (!strcmp(m_charset->csname, MY_UTF8MB3) &&
|
||||||
return true;
|
!strcmp(cs->csname, MY_UTF8MB4))
|
||||||
|
|
||||||
if (!strcmp(old_cs_name, "ascii") && !(new_ci->state & MY_CS_NONASCII))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!strcmp(old_cs_name, "ucs2") && !strcmp(new_cs_name, "utf16"))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Originally we allowed here instat ALTER for ASCII-to-LATIN1
|
||||||
|
and UCS2-to-UTF16, but this was wrong:
|
||||||
|
- MariaDB's ascii is not a subset for 8-bit character sets
|
||||||
|
like latin1, because it allows storing bytes 0x80..0xFF as
|
||||||
|
"unassigned" characters (see MDEV-19285).
|
||||||
|
- MariaDB's ucs2 (as in Unicode-1.1) is not a subset for UTF16,
|
||||||
|
because they treat surrogate codes differently (MDEV-19284).
|
||||||
|
*/
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type_handler::Charsets_are_compatible(const CHARSET_INFO *old_ci,
|
|
||||||
const CHARSET_INFO *new_ci,
|
|
||||||
bool part_of_a_key)
|
|
||||||
{
|
|
||||||
const char *old_cs_name= old_ci->csname;
|
|
||||||
const char *new_cs_name= new_ci->csname;
|
|
||||||
|
|
||||||
if (!charsets_are_compatible(old_cs_name, new_ci))
|
bool
|
||||||
|
Charset::encoding_and_order_allow_reinterpret_as(CHARSET_INFO *cs) const
|
||||||
{
|
{
|
||||||
|
if (!encoding_allows_reinterpret_as(cs))
|
||||||
return false;
|
return false;
|
||||||
}
|
LEX_CSTRING name0= collation_specific_name();
|
||||||
|
LEX_CSTRING name1= Charset(cs).collation_specific_name();
|
||||||
if (!part_of_a_key)
|
return name0.length && !cmp(&name0, &name1);
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(old_ci->name + strlen(old_cs_name),
|
|
||||||
new_ci->name + strlen(new_cs_name)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -3705,10 +3705,6 @@ public:
|
|||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
Vers_history_point_resolve_unit(THD *thd, Vers_history_point *point) const;
|
Vers_history_point_resolve_unit(THD *thd, Vers_history_point *point) const;
|
||||||
|
|
||||||
static bool Charsets_are_compatible(const CHARSET_INFO *old_ci,
|
|
||||||
const CHARSET_INFO *new_ci,
|
|
||||||
bool part_of_a_key);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user