mirror of
https://github.com/MariaDB/server.git
synced 2025-01-27 17:33:44 +01:00
MDEV-22771 Instant extension of CHAR column is wrongly allowed
commit 854c219a7f
(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.
This commit is contained in:
parent
956f21c3b0
commit
0a7faed75a
4 changed files with 50 additions and 40 deletions
mysql-test/suite/innodb
storage/innobase/handler
|
@ -1,29 +1,38 @@
|
||||||
--- 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);
|
||||||
|
|
Binary file not shown.
|
@ -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)
|
||||||
&& 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
|
||||||
|
|
Loading…
Add table
Reference in a new issue