summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kosov <eugene.kosov@mariadb.com>2020-07-20 13:10:22 +0300
committerEugene Kosov <eugene.kosov@mariadb.com>2020-07-20 18:53:16 +0300
commitc4d5b6b157b06fe22fd7e01967d7a0194c3686a2 (patch)
tree2421b0c639c80e3de9b14d32ff99b2387de5e8ac
parent4b959bd8df18a281248c7325a61f4a79ce7691da (diff)
downloadmariadb-git-c4d5b6b157b06fe22fd7e01967d7a0194c3686a2.tar.gz
MDEV-22899 Assertion `field->col->is_binary() || field->prefix_len % field->col->mbmaxlen == 0' failed in dict_index_add_to_cache
is_part_of_a_key(): detect is TEXT field is a part of some key ha_innobase::can_convert_blob(): now correctly detect whether our blob is a part of some key. Previously the check didn't work in some cases.
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_charset.result63
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_charset.test73
-rw-r--r--storage/innobase/handler/ha_innodb.cc62
3 files changed, 172 insertions, 26 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter_charset.result b/mysql-test/suite/innodb/r/instant_alter_charset.result
index cbb49819bfe..9e7dab8f7b4 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 270db2d6462..b14c7861c25 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 6d100576c20..1b3237459ba 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(