mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-17301 Change of COLLATE unnecessarily requires ALGORITHM=COPY
Patch is about two cases: 1) On some collate changes it's possible to rebuild only secondary indexes 2) For non-indexed columns collate can be changed INSTANTly Implemented mostly in Field_{string,varstring,blob}::is_equal(). Make this method return how exactly collationa differs. This information is later used by fill_alter_inplace_info() to pass correct info to engine.
This commit is contained in:
@ -1,10 +1,51 @@
|
||||
--- instant_alter_charset.result 2019-04-23 17:42:23.324326518 +0400
|
||||
+++ instant_alter_charset,redundant.result 2019-04-23 17:42:46.047531591 +0400
|
||||
--- instant_alter_charset.result 2019-06-17 14:36:02.311515062 +0300
|
||||
+++ instant_alter_charset,redundant.result 2019-06-17 14:50:11.888705725 +0300
|
||||
@@ -279,7 +279,6 @@
|
||||
alter table boundary_255
|
||||
modify a varchar(70) charset utf8mb4,
|
||||
algorithm=instant;
|
||||
-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY
|
||||
drop table boundary_255;
|
||||
create table fully_compatible (
|
||||
id int auto_increment unique key,
|
||||
create table t (
|
||||
a char(10) collate utf8mb3_general_ci,
|
||||
@@ -297,32 +296,21 @@
|
||||
repeat('a', 10), repeat('a', 10)
|
||||
);
|
||||
alter table t modify a char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
-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 b char(70) collate utf8mb4_general_ci, algorithm=instant;
|
||||
-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 c char(100) collate utf8mb4_general_ci, algorithm=instant;
|
||||
-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 aa char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
-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;
|
||||
-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;
|
||||
-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 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: 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
|
||||
|
@ -281,6 +281,52 @@ modify a varchar(70) charset utf8mb4,
|
||||
algorithm=instant;
|
||||
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY
|
||||
drop table boundary_255;
|
||||
create table t (
|
||||
a char(10) collate utf8mb3_general_ci,
|
||||
b char(70) collate utf8mb3_general_ci,
|
||||
c char(100) collate utf8mb3_general_ci,
|
||||
aa char(10) collate utf8mb3_general_ci unique,
|
||||
bb char(70) collate utf8mb3_general_ci unique,
|
||||
cc char(100) collate utf8mb3_general_ci unique,
|
||||
d char(10) collate utf8mb3_general_ci,
|
||||
dd char(10) collate utf8mb3_general_ci unique
|
||||
) engine=innodb;
|
||||
insert into t values
|
||||
(repeat('a', 10), repeat('a', 70), repeat('a', 100),
|
||||
repeat('a', 10), repeat('a', 70), repeat('a', 100),
|
||||
repeat('a', 10), repeat('a', 10)
|
||||
);
|
||||
alter table t modify a char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
alter table t modify b char(70) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
alter table t modify c char(100) collate utf8mb4_general_ci, algorithm=instant;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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: ADD INDEX. Try ALGORITHM=NOCOPY
|
||||
select * from t;
|
||||
a b c aa bb cc d dd
|
||||
aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaa aaaaaaaaaa
|
||||
drop table t;
|
||||
create table fully_compatible (
|
||||
id int auto_increment unique key,
|
||||
from_charset char(255),
|
||||
@ -784,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: Cannot change column type. 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;
|
||||
@ -801,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: Cannot change column type. 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;
|
||||
@ -818,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: Cannot change column type. 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;
|
||||
@ -835,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: Cannot change column type. 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;
|
||||
@ -852,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: Cannot change column type. 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;
|
||||
@ -869,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: Cannot change column type. 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;
|
||||
@ -886,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: Cannot change column type. 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;
|
||||
@ -903,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: Cannot change column type. 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;
|
||||
@ -920,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: Cannot change column type. 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;
|
||||
@ -937,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: Cannot change column type. 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;
|
||||
@ -954,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: Cannot change column type. 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;
|
||||
@ -1827,3 +1873,48 @@ CREATE TABLE t1 (a VARCHAR(1), UNIQUE(a)) ENGINE=InnoDB;
|
||||
ALTER TABLE t1 MODIFY a INT, ADD b INT, ADD UNIQUE (b), ALGORITHM=INSTANT;
|
||||
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-17301 Change of COLLATE unnecessarily requires ALGORITHM=COPY
|
||||
#
|
||||
create table t (
|
||||
a char(10) collate latin1_general_ci primary key,
|
||||
b char(10) collate latin1_general_ci,
|
||||
c char(10) collate latin1_general_ci,
|
||||
unique key b_key(b)
|
||||
) engine=innodb;
|
||||
insert into t values
|
||||
('aaa', 'aaa', 'aaa'), ('ccc', 'ccc', 'ccc'), ('bbb', 'bbb', 'bbb');
|
||||
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: ADD INDEX. Try ALGORITHM=NOCOPY
|
||||
alter table t modify b char(10) collate latin1_general_cs, algorithm=nocopy;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
alter table t modify c char(10) collate latin1_general_cs, algorithm=instant;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
drop table t;
|
||||
create table t (
|
||||
a varchar(10) collate latin1_general_ci primary key,
|
||||
b varchar(10) collate latin1_general_ci,
|
||||
c varchar(10) collate latin1_general_ci,
|
||||
unique key b_key(b)
|
||||
) engine=innodb;
|
||||
insert into t values
|
||||
('aaa', 'aaa', 'aaa'), ('ccc', 'ccc', 'ccc'), ('bbb', 'bbb', 'bbb');
|
||||
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: ADD INDEX. Try ALGORITHM=NOCOPY
|
||||
alter table t modify b varchar(10) collate latin1_general_cs, algorithm=nocopy;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
alter table t modify c varchar(10) collate latin1_general_cs, algorithm=instant;
|
||||
check table t;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t check status OK
|
||||
drop table t;
|
||||
|
@ -321,6 +321,67 @@ alter table boundary_255
|
||||
|
||||
drop table boundary_255;
|
||||
|
||||
|
||||
create table t (
|
||||
a char(10) collate utf8mb3_general_ci,
|
||||
b char(70) collate utf8mb3_general_ci,
|
||||
c char(100) collate utf8mb3_general_ci,
|
||||
|
||||
aa char(10) collate utf8mb3_general_ci unique,
|
||||
bb char(70) collate utf8mb3_general_ci unique,
|
||||
cc char(100) collate utf8mb3_general_ci unique,
|
||||
|
||||
d char(10) collate utf8mb3_general_ci,
|
||||
dd char(10) collate utf8mb3_general_ci unique
|
||||
) engine=innodb;
|
||||
insert into t values
|
||||
(repeat('a', 10), repeat('a', 70), repeat('a', 100),
|
||||
repeat('a', 10), repeat('a', 70), repeat('a', 100),
|
||||
repeat('a', 10), repeat('a', 10)
|
||||
);
|
||||
if ($row_format != 'redundant') {
|
||||
alter table t modify a char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
alter table t modify b char(70) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
alter table t modify c char(100) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
|
||||
alter table t modify aa char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
alter table t modify bb char(70) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
alter table t modify cc char(100) collate utf8mb4_general_ci, algorithm=instant;
|
||||
check table t;
|
||||
|
||||
alter table t modify d char(10) collate utf8mb4_spanish_ci, algorithm=instant;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify dd char(10) collate utf8mb4_spanish_ci, algorithm=instant;
|
||||
}
|
||||
if ($row_format == 'redundant') {
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify a char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify b char(70) collate utf8mb4_general_ci, algorithm=instant;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify c char(100) collate utf8mb4_general_ci, algorithm=instant;
|
||||
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify aa char(10) collate utf8mb4_general_ci, algorithm=instant;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify bb char(70) collate utf8mb4_general_ci, algorithm=instant;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify cc char(100) collate utf8mb4_general_ci, algorithm=instant;
|
||||
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify d char(10) collate utf8mb4_spanish_ci, algorithm=instant;
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
alter table t modify dd char(10) collate utf8mb4_spanish_ci, algorithm=instant;
|
||||
}
|
||||
select * from t;
|
||||
drop table t;
|
||||
|
||||
|
||||
create table fully_compatible (
|
||||
id int auto_increment unique key,
|
||||
from_charset char(255),
|
||||
@ -604,3 +665,53 @@ CREATE TABLE t1 (a VARCHAR(1), UNIQUE(a)) ENGINE=InnoDB;
|
||||
ALTER TABLE t1 MODIFY a INT, ADD b INT, ADD UNIQUE (b), ALGORITHM=INSTANT;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-17301 Change of COLLATE unnecessarily requires ALGORITHM=COPY
|
||||
--echo #
|
||||
|
||||
create table t (
|
||||
a char(10) collate latin1_general_ci primary key,
|
||||
b char(10) collate latin1_general_ci,
|
||||
c char(10) collate latin1_general_ci,
|
||||
unique key b_key(b)
|
||||
) engine=innodb;
|
||||
|
||||
insert into t values
|
||||
('aaa', 'aaa', 'aaa'), ('ccc', 'ccc', 'ccc'), ('bbb', 'bbb', 'bbb');
|
||||
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
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;
|
||||
alter table t modify b char(10) collate latin1_general_cs, algorithm=nocopy;
|
||||
check table t;
|
||||
|
||||
alter table t modify c char(10) collate latin1_general_cs, algorithm=instant;
|
||||
check table t;
|
||||
|
||||
drop table t;
|
||||
|
||||
create table t (
|
||||
a varchar(10) collate latin1_general_ci primary key,
|
||||
b varchar(10) collate latin1_general_ci,
|
||||
c varchar(10) collate latin1_general_ci,
|
||||
unique key b_key(b)
|
||||
) engine=innodb;
|
||||
|
||||
insert into t values
|
||||
('aaa', 'aaa', 'aaa'), ('ccc', 'ccc', 'ccc'), ('bbb', 'bbb', 'bbb');
|
||||
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
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;
|
||||
alter table t modify b varchar(10) collate latin1_general_cs, algorithm=nocopy;
|
||||
check table t;
|
||||
|
||||
alter table t modify c varchar(10) collate latin1_general_cs, algorithm=instant;
|
||||
check table t;
|
||||
|
||||
drop table t;
|
||||
|
99
sql/field.cc
99
sql/field.cc
@ -7073,36 +7073,40 @@ int Field_str::store(double nr)
|
||||
return store(buff, (uint)length, &my_charset_numeric);
|
||||
}
|
||||
|
||||
|
||||
bool Field_longstr::
|
||||
csinfo_change_allows_instant_alter(const Create_field *to) const
|
||||
uint Field_longstr::
|
||||
is_equal_for_different_charsets(const Column_definition &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);
|
||||
}
|
||||
Charset field_cs(field_charset);
|
||||
if (!field_cs.encoding_allows_reinterpret_as(to.charset))
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (!field_cs.eq_collation_specific_names(to.charset))
|
||||
return IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE;
|
||||
|
||||
return IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET;
|
||||
}
|
||||
|
||||
uint Field_string::is_equal(Create_field *new_field)
|
||||
{
|
||||
DBUG_ASSERT(!compression_method());
|
||||
if (new_field->type_handler() != type_handler())
|
||||
return IS_EQUAL_NO;
|
||||
if (new_field->length < max_display_length())
|
||||
return IS_EQUAL_NO;
|
||||
if (new_field->char_length < char_length())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (!csinfo_change_allows_instant_alter(new_field))
|
||||
if (new_field->charset != field_charset)
|
||||
{
|
||||
if (new_field->length != max_display_length() &&
|
||||
table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
return is_equal_for_different_charsets(*new_field);
|
||||
}
|
||||
|
||||
if (new_field->length != max_display_length())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (new_field->length == max_display_length())
|
||||
return new_field->charset == field_charset
|
||||
? IS_EQUAL_YES : IS_EQUAL_PACK_LENGTH;
|
||||
|
||||
return IS_EQUAL_NO;
|
||||
return IS_EQUAL_YES;
|
||||
}
|
||||
|
||||
|
||||
@ -7936,6 +7940,20 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table,
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
This check is InnoDB specific. ROW_FORMAT=REDUNDANT always allows such
|
||||
enlargement. But other row formats can do this only for particular current
|
||||
and new lengths. This is because InnoDB stores VARCHAR length in one or two
|
||||
bytes.
|
||||
*/
|
||||
static bool supports_such_enlargement(const Field *field,
|
||||
const Create_field *new_field)
|
||||
{
|
||||
return field->field_length <= 127 || new_field->length <= 255 ||
|
||||
field->field_length > 255 ||
|
||||
(field->table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION);
|
||||
}
|
||||
|
||||
uint Field_varstring::is_equal(Create_field *new_field)
|
||||
{
|
||||
if (new_field->length < field_length)
|
||||
@ -7944,24 +7962,26 @@ uint Field_varstring::is_equal(Create_field *new_field)
|
||||
return IS_EQUAL_NO;
|
||||
if (!new_field->compression_method() != !compression_method())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (!csinfo_change_allows_instant_alter(new_field))
|
||||
if (new_field->type_handler() != type_handler())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
const Type_handler *new_type_handler= new_field->type_handler();
|
||||
if (new_type_handler == type_handler())
|
||||
if (new_field->charset != field_charset)
|
||||
{
|
||||
if (new_field->length == field_length)
|
||||
return new_field->charset == field_charset
|
||||
? IS_EQUAL_YES : IS_EQUAL_PACK_LENGTH;
|
||||
if (field_length <= 127 ||
|
||||
new_field->length <= 255 ||
|
||||
field_length > 255 ||
|
||||
(table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION))
|
||||
return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length
|
||||
if (!supports_such_enlargement(this, new_field))
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
return is_equal_for_different_charsets(*new_field);
|
||||
}
|
||||
|
||||
return IS_EQUAL_NO;
|
||||
if (new_field->length != field_length)
|
||||
{
|
||||
if (!supports_such_enlargement(this, new_field))
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length
|
||||
}
|
||||
|
||||
return IS_EQUAL_YES;
|
||||
}
|
||||
|
||||
|
||||
@ -8728,25 +8748,16 @@ uint Field_blob::max_packed_col_length(uint max_length)
|
||||
uint Field_blob::is_equal(Create_field *new_field)
|
||||
{
|
||||
if (new_field->type_handler() != type_handler())
|
||||
{
|
||||
return IS_EQUAL_NO;
|
||||
}
|
||||
if (!new_field->compression_method() != !compression_method())
|
||||
{
|
||||
return IS_EQUAL_NO;
|
||||
}
|
||||
if (new_field->pack_length != pack_length())
|
||||
{
|
||||
return IS_EQUAL_NO;
|
||||
}
|
||||
|
||||
if (!csinfo_change_allows_instant_alter(new_field))
|
||||
if (!new_field->compression_method() != !compression_method())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (new_field->pack_length != pack_length())
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
if (field_charset != new_field->charset)
|
||||
{
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
}
|
||||
return is_equal_for_different_charsets(*new_field);
|
||||
|
||||
return IS_EQUAL_YES;
|
||||
}
|
||||
|
@ -1928,7 +1928,8 @@ protected:
|
||||
CHARSET_INFO *cs, size_t nchars);
|
||||
String *uncompress(String *val_buffer, String *val_ptr,
|
||||
const uchar *from, uint from_length);
|
||||
bool csinfo_change_allows_instant_alter(const Create_field *to) const;
|
||||
uint is_equal_for_different_charsets(const Column_definition &to) const;
|
||||
|
||||
public:
|
||||
Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
|
||||
uchar null_bit_arg, utype unireg_check_arg,
|
||||
|
@ -354,6 +354,14 @@
|
||||
data dictionary without changing table rows
|
||||
*/
|
||||
#define IS_EQUAL_PACK_LENGTH 2
|
||||
/**
|
||||
charsets are the same or compatible, collates are the same, the rest is equal
|
||||
*/
|
||||
#define IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET 3
|
||||
/**
|
||||
charsets are the same or compatible, collates are different, the rest is equal
|
||||
*/
|
||||
#define IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE 4
|
||||
|
||||
enum enum_parsing_place
|
||||
{
|
||||
|
@ -167,7 +167,7 @@ public:
|
||||
*/
|
||||
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;
|
||||
bool eq_collation_specific_names(CHARSET_INFO *cs) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -6568,15 +6568,19 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
|
||||
((Field_varstring *) old_field)->length_bytes);
|
||||
}
|
||||
|
||||
uint is_equal= key_part->field->is_equal(new_field);
|
||||
if (key_part->length == old_field_len &&
|
||||
key_part->length < new_part->length &&
|
||||
(key_part->field->is_equal((Create_field *) new_field) ==
|
||||
IS_EQUAL_PACK_LENGTH))
|
||||
(is_equal == IS_EQUAL_PACK_LENGTH ||
|
||||
is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET))
|
||||
{
|
||||
result= Compare_keys::EqualButKeyPartLength;
|
||||
}
|
||||
else if (key_part->length != new_part->length)
|
||||
return Compare_keys::NotEqual;
|
||||
|
||||
if (is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE)
|
||||
return Compare_keys::NotEqual;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -6598,6 +6602,40 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Change Field::is_equal() result depending on field being a part of some index.
|
||||
*/
|
||||
static uint process_is_equal_result_for_key_parts(uint is_equal,
|
||||
const Field *old_field,
|
||||
const Create_field *new_field)
|
||||
{
|
||||
if (is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET)
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
|
||||
if (is_equal == IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE)
|
||||
{
|
||||
bool part_of_a_key= !new_field->field->part_of_key.is_clear_all();
|
||||
|
||||
if (part_of_a_key)
|
||||
{
|
||||
const TABLE_SHARE *s= new_field->field->table->s;
|
||||
|
||||
bool part_of_a_primary_key=
|
||||
s->primary_key != MAX_KEY &&
|
||||
new_field->field->part_of_key.is_set(s->primary_key);
|
||||
|
||||
if (part_of_a_primary_key)
|
||||
return IS_EQUAL_NO;
|
||||
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
}
|
||||
|
||||
return IS_EQUAL_PACK_LENGTH;
|
||||
}
|
||||
|
||||
return is_equal;
|
||||
}
|
||||
|
||||
/**
|
||||
Compare original and new versions of a table and fill Alter_inplace_info
|
||||
describing differences between those versions.
|
||||
@ -6735,7 +6773,7 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
||||
Check if type of column has changed to some incompatible type.
|
||||
*/
|
||||
uint is_equal= field->is_equal(new_field);
|
||||
switch (is_equal)
|
||||
switch (process_is_equal_result_for_key_parts(is_equal, field, new_field))
|
||||
{
|
||||
case IS_EQUAL_NO:
|
||||
/* New column type is incompatible with old one. */
|
||||
|
@ -8363,20 +8363,10 @@ Charset::encoding_allows_reinterpret_as(const CHARSET_INFO *cs) const
|
||||
|
||||
|
||||
bool
|
||||
Charset::encoding_and_order_allow_reinterpret_as(CHARSET_INFO *cs) const
|
||||
Charset::eq_collation_specific_names(CHARSET_INFO *cs) const
|
||||
{
|
||||
/*
|
||||
Test quickly if we have two exactly equal CHARSET_INFO pointers.
|
||||
This also handles a special case with my_charset_bin:
|
||||
it does not have a collation name specific part in CHARSET_INFO::name,
|
||||
which is just "binary" (without a character set name prefix),
|
||||
so the code with collation_specific_name() below won't work for it.
|
||||
*/
|
||||
if (m_charset == cs)
|
||||
return true;
|
||||
if (!encoding_allows_reinterpret_as(cs))
|
||||
return false;
|
||||
LEX_CSTRING name0= collation_specific_name();
|
||||
LEX_CSTRING name1= Charset(cs).collation_specific_name();
|
||||
/* Empty collations are not equal */
|
||||
return name0.length && !cmp(&name0, &name1);
|
||||
}
|
||||
|
@ -9120,14 +9120,20 @@ innobase_rename_or_enlarge_column_try(
|
||||
DBUG_ASSERT(col->len <= len);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_ad(col->mbminlen <= col->mbmaxlen);
|
||||
switch (mtype) {
|
||||
case DATA_MYSQL:
|
||||
if (!(prtype & DATA_BINARY_TYPE) || user_table->not_redundant()
|
||||
|| col->mbminlen != col->mbmaxlen) {
|
||||
/* NOTE: we could allow this when !(prtype &
|
||||
DATA_BINARY_TYPE) and ROW_FORMAT is not REDUNDANT and
|
||||
mbminlen<mbmaxlen. That is, we treat a UTF-8 CHAR(n)
|
||||
column somewhat like a VARCHAR. */
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_CHAR:
|
||||
case DATA_MYSQL:
|
||||
/* NOTE: we could allow this when !(prtype & DATA_BINARY_TYPE)
|
||||
and ROW_FORMAT is not REDUNDANT and mbminlen<mbmaxlen.
|
||||
That is, we treat a UTF-8 CHAR(n) column somewhat like
|
||||
a VARCHAR. */
|
||||
ut_ad(col->len == len);
|
||||
break;
|
||||
case DATA_BINARY:
|
||||
|
Reference in New Issue
Block a user