mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-34376 Wrong data types when mixing an utf8 *TEXT column and a short binary
A mixture of a multi-byte *TEXT column and a short binary column produced a too large column. For example, COALESCE(tinytext_utf8mb4, short_varbinary) produced a BLOB column instead of an expected TINYBLOB. - Adding a virtual method Type_all_attributes::character_octet_length(), returning max_length by default. - Overriding Item_field::character_octet_length() to extract the octet length from the underlying Field. - Overriding Item_ref::character_octet_length() to extract the octet length from the references Item (e.g. as VIEW fields). - Fixing Type_numeric_attributes::find_max_octet_length() to take the octet length using the new method character_octet_length() instead of accessing max_length directly.
This commit is contained in:
@ -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
|
||||
#
|
||||
|
@ -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 #
|
||||
|
12
sql/item.h
12
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<Item_ref*>(this)->Item_ref::real_item();
|
||||
}
|
||||
const TYPELIB *get_typelib() const override
|
||||
{
|
||||
return ref ? (*ref)->get_typelib() : NULL;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user