diff --git a/mysql-test/main/ctype_utf8mb4.result b/mysql-test/main/ctype_utf8mb4.result index 64f28bd4bf3..bc370b2a694 100644 --- a/mysql-test/main/ctype_utf8mb4.result +++ b/mysql-test/main/ctype_utf8mb4.result @@ -4165,5 +4165,126 @@ SELECT 1 COLLATE utf8mb4_bin; SELECT 1 COLLATE latin1_swedish_ci; ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8mb4' # +# MDEV-34376 Wrong data types when mixing an utf8 *TEXT column and a short binary +# +CREATE TABLE t1 ( +c_tinytext tinytext, +c_text text, +c_mediumtext mediumtext, +c_longtext longtext +) CHARACTER SET utf8mb4; +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE VIEW v2 AS SELECT * FROM v1; +# Using table fields +CREATE TABLE t2 AS SELECT +COALESCE(c_tinytext, CAST('binary data' AS BINARY)) AS mix_tinytext_binary, +COALESCE(c_text, CAST('binary data' AS BINARY)) AS mix_text_binary, +COALESCE(c_mediumtext, CAST('binary data' AS BINARY)) AS mix_mediumtext_binary, +COALESCE(c_longtext, CAST('binary data' AS BINARY)) AS mix_longtext_binary +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `mix_tinytext_binary` tinyblob DEFAULT NULL, + `mix_text_binary` blob DEFAULT NULL, + `mix_mediumtext_binary` mediumblob DEFAULT NULL, + `mix_longtext_binary` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +c_tinytext AS mix_tinytext_binary, +c_text AS mix_text_binary, +c_mediumtext AS mix_mediumtext_binary, +c_longtext AS mix_longtext_binary +FROM t1 +UNION SELECT +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `mix_tinytext_binary` tinyblob DEFAULT NULL, + `mix_text_binary` blob DEFAULT NULL, + `mix_mediumtext_binary` mediumblob DEFAULT NULL, + `mix_longtext_binary` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +# Using view fields +CREATE TABLE t2 AS SELECT +COALESCE(c_tinytext, CAST('binary data' AS BINARY)) AS mix_tinytext_binary, +COALESCE(c_text, CAST('binary data' AS BINARY)) AS mix_text_binary, +COALESCE(c_mediumtext, CAST('binary data' AS BINARY)) AS mix_mediumtext_binary, +COALESCE(c_longtext, CAST('binary data' AS BINARY)) AS mix_longtext_binary +FROM v1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `mix_tinytext_binary` tinyblob DEFAULT NULL, + `mix_text_binary` blob DEFAULT NULL, + `mix_mediumtext_binary` mediumblob DEFAULT NULL, + `mix_longtext_binary` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +c_tinytext AS mix_tinytext_binary, +c_text AS mix_text_binary, +c_mediumtext AS mix_mediumtext_binary, +c_longtext AS mix_longtext_binary +FROM v1 +UNION SELECT +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `mix_tinytext_binary` tinyblob DEFAULT NULL, + `mix_text_binary` blob DEFAULT NULL, + `mix_mediumtext_binary` mediumblob DEFAULT NULL, + `mix_longtext_binary` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +# Using view on view fields +CREATE TABLE t2 AS SELECT +COALESCE(c_tinytext, CAST('binary data' AS BINARY)) AS mix_tinytext_binary, +COALESCE(c_text, CAST('binary data' AS BINARY)) AS mix_text_binary, +COALESCE(c_mediumtext, CAST('binary data' AS BINARY)) AS mix_mediumtext_binary, +COALESCE(c_longtext, CAST('binary data' AS BINARY)) AS mix_longtext_binary +FROM v2; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `mix_tinytext_binary` tinyblob DEFAULT NULL, + `mix_text_binary` blob DEFAULT NULL, + `mix_mediumtext_binary` mediumblob DEFAULT NULL, + `mix_longtext_binary` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +CREATE TABLE t2 AS SELECT +c_tinytext AS mix_tinytext_binary, +c_text AS mix_text_binary, +c_mediumtext AS mix_mediumtext_binary, +c_longtext AS mix_longtext_binary +FROM v2 +UNION SELECT +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY), +CAST('binary data' AS BINARY); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `mix_tinytext_binary` tinyblob DEFAULT NULL, + `mix_text_binary` blob DEFAULT NULL, + `mix_mediumtext_binary` mediumblob DEFAULT NULL, + `mix_longtext_binary` longblob DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +DROP TABLE t2; +DROP VIEW v2, v1; +DROP TABLE t1; +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_utf8mb4.test b/mysql-test/main/ctype_utf8mb4.test index c0c5568b3bd..6361252ab80 100644 --- a/mysql-test/main/ctype_utf8mb4.test +++ b/mysql-test/main/ctype_utf8mb4.test @@ -2062,6 +2062,99 @@ SELECT 1 COLLATE utf8mb4_bin; --error ER_COLLATION_CHARSET_MISMATCH SELECT 1 COLLATE latin1_swedish_ci; +--echo # +--echo # MDEV-34376 Wrong data types when mixing an utf8 *TEXT column and a short binary +--echo # + +CREATE TABLE t1 ( + c_tinytext tinytext, + c_text text, + c_mediumtext mediumtext, + c_longtext longtext +) CHARACTER SET utf8mb4; +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE VIEW v2 AS SELECT * FROM v1; + +--echo # Using table fields + +CREATE TABLE t2 AS SELECT + COALESCE(c_tinytext, CAST('binary data' AS BINARY)) AS mix_tinytext_binary, + COALESCE(c_text, CAST('binary data' AS BINARY)) AS mix_text_binary, + COALESCE(c_mediumtext, CAST('binary data' AS BINARY)) AS mix_mediumtext_binary, + COALESCE(c_longtext, CAST('binary data' AS BINARY)) AS mix_longtext_binary +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT + c_tinytext AS mix_tinytext_binary, + c_text AS mix_text_binary, + c_mediumtext AS mix_mediumtext_binary, + c_longtext AS mix_longtext_binary +FROM t1 +UNION SELECT + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY); +SHOW CREATE TABLE t2; +DROP TABLE t2; + + +--echo # Using view fields + +CREATE TABLE t2 AS SELECT + COALESCE(c_tinytext, CAST('binary data' AS BINARY)) AS mix_tinytext_binary, + COALESCE(c_text, CAST('binary data' AS BINARY)) AS mix_text_binary, + COALESCE(c_mediumtext, CAST('binary data' AS BINARY)) AS mix_mediumtext_binary, + COALESCE(c_longtext, CAST('binary data' AS BINARY)) AS mix_longtext_binary +FROM v1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT + c_tinytext AS mix_tinytext_binary, + c_text AS mix_text_binary, + c_mediumtext AS mix_mediumtext_binary, + c_longtext AS mix_longtext_binary +FROM v1 +UNION SELECT + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY); +SHOW CREATE TABLE t2; +DROP TABLE t2; + + +--echo # Using view on view fields + +CREATE TABLE t2 AS SELECT + COALESCE(c_tinytext, CAST('binary data' AS BINARY)) AS mix_tinytext_binary, + COALESCE(c_text, CAST('binary data' AS BINARY)) AS mix_text_binary, + COALESCE(c_mediumtext, CAST('binary data' AS BINARY)) AS mix_mediumtext_binary, + COALESCE(c_longtext, CAST('binary data' AS BINARY)) AS mix_longtext_binary +FROM v2; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 AS SELECT + c_tinytext AS mix_tinytext_binary, + c_text AS mix_text_binary, + c_mediumtext AS mix_mediumtext_binary, + c_longtext AS mix_longtext_binary +FROM v2 +UNION SELECT + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY), + CAST('binary data' AS BINARY); +SHOW CREATE TABLE t2; +DROP TABLE t2; + +DROP VIEW v2, v1; +DROP TABLE t1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/sql/item.h b/sql/item.h index 796b2ec9eee..9af0a077f75 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3576,6 +3576,10 @@ public: return &type_handler_null; return field->type_handler(); } + uint32 character_octet_length() const override + { + return field->character_octet_length(); + } Field *create_tmp_field_from_item_field(MEM_ROOT *root, TABLE *new_table, Item_ref *orig_item, const Tmp_field_param *param); @@ -5578,6 +5582,10 @@ public: { return (*ref)->type_handler(); } const Type_handler *real_type_handler() const override { return (*ref)->real_type_handler(); } + uint32 character_octet_length() const override + { + return Item_ref::real_item()->character_octet_length(); + } Field *get_tmp_table_field() override { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd) override; @@ -5616,6 +5624,10 @@ public: (*ref)->save_in_field(result_field, no_conversions); } Item *real_item() override { return ref ? (*ref)->real_item() : this; } + const Item *real_item() const + { + return const_cast(this)->Item_ref::real_item(); + } const TYPELIB *get_typelib() const override { return ref ? (*ref)->get_typelib() : NULL; diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 9ede9e2582d..44475e29bcc 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1221,7 +1221,7 @@ uint32 Type_numeric_attributes::find_max_octet_length(Item **item, uint nitems) { uint32 octet_length= 0; for (uint i= 0; i < nitems ; i++) - set_if_bigger(octet_length, item[i]->max_length); + set_if_bigger(octet_length, item[i]->character_octet_length()); return octet_length; } diff --git a/sql/sql_type.h b/sql/sql_type.h index 874623e4316..859b63b5ad1 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3345,6 +3345,7 @@ public: { } virtual ~Type_all_attributes() = default; virtual void set_maybe_null(bool maybe_null_arg)= 0; + virtual uint32 character_octet_length() const { return max_length; } // Returns total number of decimal digits virtual uint decimal_precision() const= 0; virtual const TYPELIB *get_typelib() const= 0;