mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +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;
|
SELECT 1 COLLATE latin1_swedish_ci;
|
||||||
ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'utf8mb4'
|
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
|
# End of 10.5 tests
|
||||||
#
|
#
|
||||||
|
@@ -2062,6 +2062,99 @@ SELECT 1 COLLATE utf8mb4_bin;
|
|||||||
--error ER_COLLATION_CHARSET_MISMATCH
|
--error ER_COLLATION_CHARSET_MISMATCH
|
||||||
SELECT 1 COLLATE latin1_swedish_ci;
|
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 #
|
||||||
--echo # End of 10.5 tests
|
--echo # End of 10.5 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
12
sql/item.h
12
sql/item.h
@@ -3576,6 +3576,10 @@ public:
|
|||||||
return &type_handler_null;
|
return &type_handler_null;
|
||||||
return field->type_handler();
|
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,
|
Field *create_tmp_field_from_item_field(MEM_ROOT *root, TABLE *new_table,
|
||||||
Item_ref *orig_item,
|
Item_ref *orig_item,
|
||||||
const Tmp_field_param *param);
|
const Tmp_field_param *param);
|
||||||
@@ -5578,6 +5582,10 @@ public:
|
|||||||
{ return (*ref)->type_handler(); }
|
{ return (*ref)->type_handler(); }
|
||||||
const Type_handler *real_type_handler() const override
|
const Type_handler *real_type_handler() const override
|
||||||
{ return (*ref)->real_type_handler(); }
|
{ 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
|
Field *get_tmp_table_field() override
|
||||||
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
|
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
|
||||||
Item *get_tmp_table_item(THD *thd) override;
|
Item *get_tmp_table_item(THD *thd) override;
|
||||||
@@ -5616,6 +5624,10 @@ public:
|
|||||||
(*ref)->save_in_field(result_field, no_conversions);
|
(*ref)->save_in_field(result_field, no_conversions);
|
||||||
}
|
}
|
||||||
Item *real_item() override { return ref ? (*ref)->real_item() : this; }
|
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
|
const TYPELIB *get_typelib() const override
|
||||||
{
|
{
|
||||||
return ref ? (*ref)->get_typelib() : NULL;
|
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;
|
uint32 octet_length= 0;
|
||||||
for (uint i= 0; i < nitems ; i++)
|
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;
|
return octet_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3345,6 +3345,7 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
virtual ~Type_all_attributes() = default;
|
virtual ~Type_all_attributes() = default;
|
||||||
virtual void set_maybe_null(bool maybe_null_arg)= 0;
|
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
|
// Returns total number of decimal digits
|
||||||
virtual uint decimal_precision() const= 0;
|
virtual uint decimal_precision() const= 0;
|
||||||
virtual const TYPELIB *get_typelib() const= 0;
|
virtual const TYPELIB *get_typelib() const= 0;
|
||||||
|
Reference in New Issue
Block a user