mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
This commit is contained in:
@ -2225,6 +2225,9 @@ a
|
||||
a
|
||||
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Start of 10.3 tests
|
||||
#
|
||||
#
|
||||
# MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
|
||||
#
|
||||
@ -2257,3 +2260,54 @@ EXPLAIN SELECT * FROM t1 WHERE a='1.1';
|
||||
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
|
||||
#
|
||||
CREATE TABLE t1 (a ENUM('a'));
|
||||
# non-UNION + table column
|
||||
CREATE TABLE t2 AS SELECT (SELECT a FROM t1);
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`(SELECT a FROM t1)` varchar(1) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t2;
|
||||
# UNION + table column
|
||||
CREATE TABLE t2 AS SELECT (SELECT a FROM t1 UNION SELECT NULL);
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`(SELECT a FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t2;
|
||||
# UNION + SP variable
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE va ENUM('a');
|
||||
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`(SELECT va FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP PROCEDURE p1;
|
||||
# UNION + anchored SP variable
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE va TYPE OF t1.a;
|
||||
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`(SELECT va FROM t1 UNION SELECT NULL)` varchar(1) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP PROCEDURE p1;
|
||||
|
@ -457,6 +457,10 @@ ALTER TABLE t1 MODIFY a ENUM('2001','2002');
|
||||
ALTER TABLE t1 MODIFY a ENUM('2001','2002');
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.3 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
|
||||
@ -473,3 +477,44 @@ EXPLAIN SELECT * FROM t1 WHERE a='1x';
|
||||
EXPLAIN SELECT * FROM t1 WHERE a='1x';
|
||||
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
|
||||
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12656 Crash in CREATE..SELECT..UNION with a ENUM column and NULL
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a ENUM('a'));
|
||||
--echo # non-UNION + table column
|
||||
CREATE TABLE t2 AS SELECT (SELECT a FROM t1);
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
--echo # UNION + table column
|
||||
CREATE TABLE t2 AS SELECT (SELECT a FROM t1 UNION SELECT NULL);
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
--echo # UNION + SP variable
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE va ENUM('a');
|
||||
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
--echo # UNION + anchored SP variable
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE va TYPE OF t1.a;
|
||||
CREATE TABLE t2 AS SELECT (SELECT va FROM t1 UNION SELECT NULL);
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
11
sql/item.cc
11
sql/item.cc
@ -10072,7 +10072,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
if (aggregate_for_result(item_type_handler))
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||
Item_type_holder::type_handler()->name().ptr(),
|
||||
Item_type_holder::real_type_handler()->name().ptr(),
|
||||
item_type_handler->name().ptr(),
|
||||
"UNION");
|
||||
DBUG_RETURN(true);
|
||||
@ -10180,7 +10180,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
||||
};
|
||||
maybe_null|= item->maybe_null;
|
||||
get_full_info(item);
|
||||
set_handler(Item_type_holder::type_handler()->type_handler_for_union(this));
|
||||
/*
|
||||
Adjust data type for union, e.g.:
|
||||
- convert type_handler_null to type_handler_string
|
||||
- convert type_handler_olddecimal to type_handler_newdecimal
|
||||
- adjust varchar/blob according to max_length
|
||||
*/
|
||||
set_handler(Item_type_holder::
|
||||
real_type_handler()->type_handler_for_union(this));
|
||||
|
||||
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
|
||||
prev_decimal_int_part= decimal_int_part();
|
||||
|
15
sql/item.h
15
sql/item.h
@ -2604,11 +2604,7 @@ public:
|
||||
const Type_handler *type_handler() const
|
||||
{
|
||||
const Type_handler *handler= field->type_handler();
|
||||
// This special code for ENUM and SET should eventually be removed
|
||||
if (handler == &type_handler_enum ||
|
||||
handler == &type_handler_set)
|
||||
return &type_handler_string;
|
||||
return field->type_handler();
|
||||
return handler->type_handler_for_item_field();
|
||||
}
|
||||
enum Item_result result_type () const
|
||||
{
|
||||
@ -5792,7 +5788,10 @@ public:
|
||||
Item_type_holder(THD*, Item*);
|
||||
|
||||
const Type_handler *type_handler() const
|
||||
{ return Type_handler_hybrid_field_type::type_handler(); }
|
||||
{
|
||||
const Type_handler *handler= Type_handler_hybrid_field_type::type_handler();
|
||||
return handler->type_handler_for_item_field();
|
||||
}
|
||||
enum_field_types field_type() const
|
||||
{ return Type_handler_hybrid_field_type::field_type(); }
|
||||
enum Item_result result_type () const
|
||||
@ -5813,7 +5812,7 @@ public:
|
||||
}
|
||||
const Type_handler *real_type_handler() const
|
||||
{
|
||||
return Item_type_holder::type_handler();
|
||||
return Type_handler_hybrid_field_type::type_handler();
|
||||
}
|
||||
|
||||
enum Type type() const { return TYPE_HOLDER; }
|
||||
@ -5825,7 +5824,7 @@ public:
|
||||
bool join_types(THD *thd, Item *);
|
||||
Field *create_tmp_field(bool group, TABLE *table)
|
||||
{
|
||||
return Item_type_holder::type_handler()->
|
||||
return Item_type_holder::real_type_handler()->
|
||||
make_and_init_table_field(&name, Record_addr(maybe_null),
|
||||
*this, table);
|
||||
}
|
||||
|
@ -470,12 +470,24 @@ const Type_handler *Type_handler_row::type_handler_for_comparison() const
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
const Type_handler *Type_handler_enum::type_handler_for_item_field() const
|
||||
{
|
||||
return &type_handler_string;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_enum::cast_to_int_type_handler() const
|
||||
{
|
||||
return &type_handler_longlong;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_set::type_handler_for_item_field() const
|
||||
{
|
||||
return &type_handler_string;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_set::cast_to_int_type_handler() const
|
||||
{
|
||||
return &type_handler_longlong;
|
||||
|
@ -579,6 +579,10 @@ public:
|
||||
*/
|
||||
virtual bool is_param_long_data_type() const { return false; }
|
||||
virtual const Type_handler *type_handler_for_comparison() const= 0;
|
||||
virtual const Type_handler *type_handler_for_item_field() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
virtual const Type_handler *type_handler_for_tmp_table(const Item *) const
|
||||
{
|
||||
return this;
|
||||
@ -2053,6 +2057,7 @@ public:
|
||||
const Name name() const { return m_name_enum; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
|
||||
const Type_handler *type_handler_for_item_field() const;
|
||||
const Type_handler *cast_to_int_type_handler() const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
@ -2071,6 +2076,7 @@ public:
|
||||
const Name name() const { return m_name_set; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
|
||||
const Type_handler *type_handler_for_item_field() const;
|
||||
const Type_handler *cast_to_int_type_handler() const;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const;
|
||||
|
Reference in New Issue
Block a user