Commit fae13194 authored by Eugene Kosov's avatar Eugene Kosov Committed by Alexander Barkov

MDEV-19524 Server crashes in Bitmap<64u>::is_clear_all /...

MDEV-19524 Server crashes in Bitmap<64u>::is_clear_all / Field_longstr::csinfo_change_allows_instant_alter

compare_keys_but_name(): reorder checks to ensure that
new_field->field != NULL inside Field::is_equal()
parent dafe41ed
...@@ -1820,3 +1820,10 @@ HEX(a) ...@@ -1820,3 +1820,10 @@ HEX(a)
61 61
62 62
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-19524 Server crashes in Bitmap<64u>::is_clear_all / Field_longstr::csinfo_change_allows_instant_alter
#
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;
--source include/innodb_row_format.inc --source include/innodb_row_format.inc
#--source include/innodb_page_size.inc
--let $row_format= `SELECT @@GLOBAL.innodb_default_row_format` --let $row_format= `SELECT @@GLOBAL.innodb_default_row_format`
set names utf8; set names utf8;
...@@ -593,3 +592,15 @@ ALTER TABLE t1 ALGORITHM=INSTANT, MODIFY a VARCHAR(10) CHARACTER SET latin1 COLL ...@@ -593,3 +592,15 @@ ALTER TABLE t1 ALGORITHM=INSTANT, MODIFY a VARCHAR(10) CHARACTER SET latin1 COLL
ALTER IGNORE TABLE t1 MODIFY a VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci; ALTER IGNORE TABLE t1 MODIFY a VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_general_ci;
SELECT HEX(a) FROM t1; SELECT HEX(a) FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-19524 Server crashes in Bitmap<64u>::is_clear_all / Field_longstr::csinfo_change_allows_instant_alter
--echo #
CREATE TABLE t1 (a VARCHAR(1), UNIQUE(a)) ENGINE=InnoDB;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1 MODIFY a INT, ADD b INT, ADD UNIQUE (b), ALGORITHM=INSTANT;
DROP TABLE t1;
...@@ -6540,8 +6540,16 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key, ...@@ -6540,8 +6540,16 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
*new_part= new_key->key_part; *new_part= new_key->key_part;
key_part < end; key_part++, new_part++) key_part < end; key_part++, new_part++)
{ {
/*
For prefix keys KEY_PART_INFO::field points to cloned Field
object with adjusted length. So below we have to check field
indexes instead of simply comparing pointers to Field objects.
*/
Create_field *new_field= alter_info->create_list.elem(new_part->fieldnr); Create_field *new_field= alter_info->create_list.elem(new_part->fieldnr);
const Field *old_field= table->field[key_part->fieldnr - 1]; if (!new_field->field ||
new_field->field->field_index != key_part->fieldnr - 1)
return Compare_keys::NotEqual;
/* /*
If there is a change in index length due to column expansion If there is a change in index length due to column expansion
like varchar(X) changed to varchar(X + N) and has a compatible like varchar(X) changed to varchar(X + N) and has a compatible
...@@ -6551,6 +6559,7 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key, ...@@ -6551,6 +6559,7 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
Key definition has changed if we are using a different field or Key definition has changed if we are using a different field or
if the user key part length is different. if the user key part length is different.
*/ */
const Field *old_field= table->field[key_part->fieldnr - 1];
auto old_field_len= old_field->pack_length(); auto old_field_len= old_field->pack_length();
if (old_field->type() == MYSQL_TYPE_VARCHAR) if (old_field->type() == MYSQL_TYPE_VARCHAR)
...@@ -6568,15 +6577,6 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key, ...@@ -6568,15 +6577,6 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
} }
else if (key_part->length != new_part->length) else if (key_part->length != new_part->length)
return Compare_keys::NotEqual; return Compare_keys::NotEqual;
/*
For prefix keys KEY_PART_INFO::field points to cloned Field
object with adjusted length. So below we have to check field
indexes instead of simply comparing pointers to Field objects.
*/
if (!new_field->field ||
new_field->field->field_index != key_part->fieldnr - 1)
return Compare_keys::NotEqual;
} }
/* /*
......
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