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
|
a
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Start of 10.3 tests
|
||||||
|
#
|
||||||
#
|
#
|
||||||
# MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
|
# 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';
|
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
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
|
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');
|
ALTER TABLE t1 MODIFY a ENUM('2001','2002');
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Start of 10.3 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-12432 Range optimizer for ENUM and SET does not return "Impossible WHERE" in some case
|
--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='1x';
|
||||||
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
|
EXPLAIN SELECT * FROM t1 WHERE a='1.0';
|
||||||
EXPLAIN SELECT * FROM t1 WHERE a='1.1';
|
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))
|
if (aggregate_for_result(item_type_handler))
|
||||||
{
|
{
|
||||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
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(),
|
item_type_handler->name().ptr(),
|
||||||
"UNION");
|
"UNION");
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
@ -10180,7 +10180,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
|
|||||||
};
|
};
|
||||||
maybe_null|= item->maybe_null;
|
maybe_null|= item->maybe_null;
|
||||||
get_full_info(item);
|
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 */
|
/* Remember decimal integer part to be used in DECIMAL_RESULT handleng */
|
||||||
prev_decimal_int_part= decimal_int_part();
|
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 *type_handler() const
|
||||||
{
|
{
|
||||||
const Type_handler *handler= field->type_handler();
|
const Type_handler *handler= field->type_handler();
|
||||||
// This special code for ENUM and SET should eventually be removed
|
return handler->type_handler_for_item_field();
|
||||||
if (handler == &type_handler_enum ||
|
|
||||||
handler == &type_handler_set)
|
|
||||||
return &type_handler_string;
|
|
||||||
return field->type_handler();
|
|
||||||
}
|
}
|
||||||
enum Item_result result_type () const
|
enum Item_result result_type () const
|
||||||
{
|
{
|
||||||
@ -5792,7 +5788,10 @@ public:
|
|||||||
Item_type_holder(THD*, Item*);
|
Item_type_holder(THD*, Item*);
|
||||||
|
|
||||||
const Type_handler *type_handler() const
|
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
|
enum_field_types field_type() const
|
||||||
{ return Type_handler_hybrid_field_type::field_type(); }
|
{ return Type_handler_hybrid_field_type::field_type(); }
|
||||||
enum Item_result result_type () const
|
enum Item_result result_type () const
|
||||||
@ -5813,7 +5812,7 @@ public:
|
|||||||
}
|
}
|
||||||
const Type_handler *real_type_handler() const
|
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; }
|
enum Type type() const { return TYPE_HOLDER; }
|
||||||
@ -5825,7 +5824,7 @@ public:
|
|||||||
bool join_types(THD *thd, Item *);
|
bool join_types(THD *thd, Item *);
|
||||||
Field *create_tmp_field(bool group, TABLE *table)
|
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),
|
make_and_init_table_field(&name, Record_addr(maybe_null),
|
||||||
*this, table);
|
*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
|
const Type_handler *Type_handler_enum::cast_to_int_type_handler() const
|
||||||
{
|
{
|
||||||
return &type_handler_longlong;
|
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
|
const Type_handler *Type_handler_set::cast_to_int_type_handler() const
|
||||||
{
|
{
|
||||||
return &type_handler_longlong;
|
return &type_handler_longlong;
|
||||||
|
@ -579,6 +579,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool is_param_long_data_type() const { return false; }
|
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_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
|
virtual const Type_handler *type_handler_for_tmp_table(const Item *) const
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -2053,6 +2057,7 @@ public:
|
|||||||
const Name name() const { return m_name_enum; }
|
const Name name() const { return m_name_enum; }
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
|
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;
|
const Type_handler *cast_to_int_type_handler() const;
|
||||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
const Field *target) const;
|
const Field *target) const;
|
||||||
@ -2071,6 +2076,7 @@ public:
|
|||||||
const Name name() const { return m_name_set; }
|
const Name name() const { return m_name_set; }
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
|
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;
|
const Type_handler *cast_to_int_type_handler() const;
|
||||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
const Field *target) const;
|
const Field *target) const;
|
||||||
|
Reference in New Issue
Block a user