diff --git a/mysql-test/suite/innodb/r/instant_alter_charset.result b/mysql-test/suite/innodb/r/instant_alter_charset.result index cbb49819bfed3..9e7dab8f7b4bc 100644 --- a/mysql-test/suite/innodb/r/instant_alter_charset.result +++ b/mysql-test/suite/innodb/r/instant_alter_charset.result @@ -1929,3 +1929,66 @@ KEY a_idx(a(1)) INSERT INTO t VALUES (1, 'something in the air'); ALTER TABLE t MODIFY a text CHARSET utf8mb4; DROP TABLE t; +# +# MDEV-22899: Assertion `field->col->is_binary() || field->prefix_len % field->col->mbmaxlen == 0' failed in dict_index_add_to_cache +# +CREATE TABLE t1 ( +a text CHARACTER SET utf8 DEFAULT NULL, +KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a text CHARACTER SET utf8 DEFAULT NULL, +b int, +KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a char(200) CHARACTER SET utf8 DEFAULT NULL, +KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a char(200) CHARACTER SET utf8 DEFAULT NULL, +b int, +KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a varchar(200) CHARACTER SET utf8 DEFAULT NULL, +KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a varchar(200) CHARACTER SET utf8 DEFAULT NULL, +b int, +KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a varchar(2000) CHARACTER SET utf8 DEFAULT NULL, +KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; +CREATE TABLE t1 ( +a varchar(2000) CHARACTER SET utf8 DEFAULT NULL, +b int, +KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_charset.test b/mysql-test/suite/innodb/t/instant_alter_charset.test index 270db2d6462a6..b14c7861c25d4 100644 --- a/mysql-test/suite/innodb/t/instant_alter_charset.test +++ b/mysql-test/suite/innodb/t/instant_alter_charset.test @@ -730,3 +730,76 @@ INSERT INTO t VALUES (1, 'something in the air'); ALTER TABLE t MODIFY a text CHARSET utf8mb4; DROP TABLE t; + + +--echo # +--echo # MDEV-22899: Assertion `field->col->is_binary() || field->prefix_len % field->col->mbmaxlen == 0' failed in dict_index_add_to_cache +--echo # + +CREATE TABLE t1 ( + a text CHARACTER SET utf8 DEFAULT NULL, + KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a text CHARACTER SET utf8 DEFAULT NULL, + b int, + KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a char(200) CHARACTER SET utf8 DEFAULT NULL, + KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a char(200) CHARACTER SET utf8 DEFAULT NULL, + b int, + KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a varchar(200) CHARACTER SET utf8 DEFAULT NULL, + KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a varchar(200) CHARACTER SET utf8 DEFAULT NULL, + b int, + KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a varchar(2000) CHARACTER SET utf8 DEFAULT NULL, + KEY a_key (a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; + +CREATE TABLE t1 ( + a varchar(2000) CHARACTER SET utf8 DEFAULT NULL, + b int, + KEY a_key (b, a(1)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +INSERT INTO t1 VALUES (); +ALTER TABLE t1 MODIFY a text DEFAULT NULL; +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6d100576c20c2..1b3237459ba6a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -21074,39 +21074,49 @@ ha_innobase::can_convert_varstring(const Field_varstring* field, return true; } -bool -ha_innobase::can_convert_blob(const Field_blob* field, - const Column_definition& new_type) const +static bool is_part_of_a_key(const Field_blob *field) { - if (new_type.type_handler() != field->type_handler()) { - return false; - } + const TABLE_SHARE *s= field->table->s; - if (!new_type.compression_method() != !field->compression_method()) { - return false; - } + for (uint i= 0; i < s->keys; i++) + { + const KEY &key= s->key_info[i]; + for (uint j= 0; j < key.user_defined_key_parts; j++) + { + const KEY_PART_INFO &info= key.key_part[j]; + if (info.field->field_index == field->field_index) + return true; + } + } - if (new_type.pack_length != field->pack_length()) { - return false; - } + return false; +} - if (new_type.charset != field->charset()) { - Charset field_cs(field->charset()); - if (!field_cs.encoding_allows_reinterpret_as( - new_type.charset)) { - return false; - } +bool ha_innobase::can_convert_blob(const Field_blob *field, + const Column_definition &new_type) const +{ + if (new_type.type_handler() != field->type_handler()) + return false; - if (!field_cs.eq_collation_specific_names(new_type.charset)) { - bool is_part_of_a_key - = !field->part_of_key.is_clear_all(); - return !is_part_of_a_key; - } + if (!new_type.compression_method() != !field->compression_method()) + return false; - return true; - } + if (new_type.pack_length != field->pack_length()) + return false; - return true; + if (new_type.charset != field->charset()) + { + Charset field_cs(field->charset()); + if (!field_cs.encoding_allows_reinterpret_as(new_type.charset)) + return false; + + if (!field_cs.eq_collation_specific_names(new_type.charset)) + return !is_part_of_a_key(field); + + return true; + } + + return true; } Compare_keys ha_innobase::compare_key_parts(