Commit 0a7faed7 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-22771 Instant extension of CHAR column is wrongly allowed

commit 854c219a (MDEV-17301)
broke a constraint: Fixed-length columns cannot be extended in InnoDB
without rebuilding the table.

ha_innobase::can_convert_string(): Correct the condition. We must
not allow any instantaneous change to the length of CHAR columns
measured in characters. For any format other than ROW_FORMAT=REDUNDANT,
we can allow the length in bytes to be extended if mbminlen<mbmaxlen held
before the change of the character set.
parent 956f21c3
--- instant_alter_convert.result --- instant_alter_convert.result
+++ instant_alter_convert,utf8.result +++ instant_alter_convert,utf8.result
@@ -37,7 +37,7 @@ @@ -38,7 +38,7 @@
test.t check status OK best.t check status OK
call check_table('t'); call check_table('t');
name mtype prtype len name mtype prtype len
-a 2 800FE 200 -a 2 800FE 200
+a 13 2100FE 600 +a 13 2100FE 600
# CHAR enlargement # CHAR enlargement
alter table t modify a char(220), algorithm=instant; alter table t modify a char(220);
select count(a) from t where a = @bigval; affected rows: 2
@@ -51,7 +51,7 @@ @@ -54,7 +54,7 @@
test.t check status OK best.t check status OK
call check_table('t'); call check_table('t');
name mtype prtype len name mtype prtype len
-a 2 800FE 220 -a 2 800FE 220
+a 13 2100FE 660 +a 13 2100FE 660
ALTER TABLE t CHANGE COLUMN a a CHAR(230) BINARY;
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
@@ -69,7 +69,7 @@
best.t check status OK
call check_table('t');
name mtype prtype len
-a 13 2F00FE 230
+a 13 5300FE 690
# Convert from VARCHAR to a bigger CHAR # Convert from VARCHAR to a bigger CHAR
alter table t modify a varchar(200), algorithm=instant; alter table t modify a varchar(200);
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type. Try ALGORITHM=COPY affected rows: 2
@@ -72,7 +72,7 @@ @@ -92,7 +92,7 @@
test.t check status OK best.t check status OK
call check_table('t'); call check_table('t');
name mtype prtype len name mtype prtype len
-a 2 800FE 255 -a 2 800FE 255
+a 13 2100FE 765 +a 13 2100FE 765
# BINARY/VARBINARY test # BINARY/VARBINARY test
create or replace table t (a varbinary(300)); create or replace table t (a varbinary(300));
alter table t modify a binary(255), algorithm=instant; insert into t values(NULL);
...@@ -64,6 +64,15 @@ select a, length(a) from t where a = 'z'; ...@@ -64,6 +64,15 @@ select a, length(a) from t where a = 'z';
check table t extended; check table t extended;
call check_table('t'); call check_table('t');
--enable_info
ALTER TABLE t CHANGE COLUMN a a CHAR(230) BINARY;
ALTER TABLE t ADD COLUMN b INT FIRST;
ALTER TABLE t DROP b;
--disable_info
check table t extended;
call check_table('t');
--echo # Convert from VARCHAR to a bigger CHAR --echo # Convert from VARCHAR to a bigger CHAR
--enable_info --enable_info
alter table t modify a varchar(200); alter table t modify a varchar(200);
......
...@@ -20986,43 +20986,35 @@ is_part_of_a_primary_key(const Field* field) ...@@ -20986,43 +20986,35 @@ is_part_of_a_primary_key(const Field* field)
&& field->part_of_key.is_set(s->primary_key); && field->part_of_key.is_set(s->primary_key);
} }
bool bool ha_innobase::can_convert_string(const Field_string *field,
ha_innobase::can_convert_string(const Field_string* field, const Column_definition &new_type) const
const Column_definition& new_type) const
{ {
DBUG_ASSERT(!field->compression_method()); DBUG_ASSERT(!field->compression_method());
if (new_type.type_handler() != field->type_handler()) { if (new_type.type_handler() != field->type_handler())
return false; return false;
}
if (new_type.char_length < field->char_length()) { if (new_type.char_length != field->char_length())
return false; return false;
}
if (new_type.charset != field->charset()) { const Charset field_cs(field->charset());
if (new_type.length != field->max_display_length()
&& !m_prebuilt->table->not_redundant()) {
return IS_EQUAL_NO;
}
Charset field_cs(field->charset()); if (new_type.length != field->max_display_length() &&
if (!field_cs.encoding_allows_reinterpret_as( (!m_prebuilt->table->not_redundant() ||
new_type.charset)) { field_cs.mbminlen() == field_cs.mbmaxlen()))
return false; return false;
}
if (!field_cs.eq_collation_specific_names(new_type.charset)) { if (new_type.charset != field->charset())
return !is_part_of_a_primary_key(field); {
} if (!field_cs.encoding_allows_reinterpret_as(new_type.charset))
return false;
return true; if (!field_cs.eq_collation_specific_names(new_type.charset))
} return !is_part_of_a_primary_key(field);
if (new_type.length != field->max_display_length()) { return true;
return false; }
}
return true; return true;
} }
static bool static bool
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment