MDEV-36716 A case expression with ROW arguments in THEN crashes
The patch for SYS_REFCURSOR (MDEV-20034) overrode these methods: - Item_func_case_searched::check_arguments() - Item_func_if::check_arguments() to validate WHEN-style arguments (e.g. args[0] in case of IF) for being able to return a boolean result. However, this unintentionally removed the test for the THEN-style arguments that they are not expressions of the ROW data type. This led to a crash inside Type_handler_hybrid_field_type::aggregate_for_result on a DBUG_ASSERT that arguments are not of the ROW data type. Fix: The fix restores blocking ROW expressions in the not supported cases, to avoid the DBUG_ASSERT and to raise an SQL error instead. Blocking ROW_RESULT expressions is done per Item_func_case_expression descendant individually, instead of blocking any ROW_RESULT arguments at the Item_func_case_expression level. The fix is done taking into account the upcoming patch for associative arrays (MDEV-34319). It should be possible to pass associative array expressions into some hybrid type functions, where ROW type expressions are not possible. As a side effect, some lecagy ER_OPERAND_COLUMNS changed to a newer ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION Changes in the top affected class Item_func_case_expression: - item_func.h: Overriding Item_func_case_expression::check_arguments() to return false, without checking any arguments. Descendant validate arguments in a various different ways. No needs to block all non-scalar data type at this level, to prevent disallowing associative arrays. Changes in descendants: - item_cmpfunc.cc: Adding a test in Item_func_case_simple::aggregate_switch_and_when_arguments() preventing passing ROW_RESULT expression in predicant and WHEN in a simple CASE: CASE predicant WHEN when1 THEN .. WHEN when2 THEN .. END; This is not supported yet. Should be preferrably fixed before MDEV-34319. - item_cmpfunc.cc: Calling args[0]->type_handler()->Item_hybrid_func_fix_attributes() from Item_func_nullif::fix_length_and_dec(). This prevents a ROW expression to be passed to args[0] of NULLIF(). But will allow to pass associative arrays. args[1] is still only checked to be comparable with args[0]. No needs to add additional tests for it. - item_cmpfunc.h: Adding a call for Item_hybrid_func_fix_attributes() in Item_func_case_abbreviation2::cache_type_info(). This prevents calling the descendant functions with a ROW expression in combination with an explicit NULL in the THEN-style arguments (but will allow to pass associative arrays): IFNULL(row_expression, NULL) IFNULL(NULL, row_expression) IF(switch, row_expression, NULL) IF(switch, NULL, row_expression) NVL2(switch, row_expression, NULL) NVL2(switch, NULL, row_expression) Adding a THD* argument into involved methods. - item_cmpfunc.h: Overriding Item_func_case_abbreviation2_switch::check_arguments() to check that the first argument in IF() and NVL2() can return bool. Removing Item_func_if::check_arguments(), as it become redundant. - sql_type.cc: Fixing sql_type.cc not to disallow items[0] with ROW_RESULT. This makes it call Item_hybrid_func_fix_attributes() at the end, which block ROW arguments into THEN-style arguments of hybrid functions. But this will allow to pass Type_handler_assoc_array expressions. - sql_type.cc: Changing Type_handler_row::Item_hybrid_func_fix_attributes to raise the ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION error instead of the DBUG_ASSERT.
This commit is contained in:
parent
4fc1063796
commit
c5d8b9963a
@ -575,3 +575,90 @@ DROP TABLE t1;
|
||||
#
|
||||
# End of 10.3 test
|
||||
#
|
||||
# Start of 12.0 tests
|
||||
#
|
||||
# MDEV-36716 A case expression with ROW arguments in THEN crashes
|
||||
#
|
||||
SELECT CASE WHEN TRUE THEN ROW(1,2) ELSE ROW(2,1) END;
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'case'
|
||||
SELECT CASE WHEN TRUE THEN ROW(1,2) ELSE NULL END;
|
||||
ERROR HY000: Illegal parameter data types row and null for operation 'case'
|
||||
SELECT CASE WHEN TRUE THEN NULL ELSE ROW(2,1) END;
|
||||
ERROR HY000: Illegal parameter data types null and row for operation 'case'
|
||||
SELECT CASE WHEN TRUE THEN ROW(2,1) END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'case'
|
||||
SELECT CASE WHEN ROW(1,2) THEN 0 WHEN ROW(2,1) THEN 1 END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'case'
|
||||
SELECT CASE WHEN ROW(1,2) THEN 0 END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'case'
|
||||
SELECT CASE WHEN NULL THEN 0 WHEN ROW(1,2) THEN 0 END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'case'
|
||||
SELECT CASE WHEN ROW(1,2) THEN 0 WHEN NULL THEN 0 END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'case'
|
||||
SELECT CASE TRUE WHEN TRUE THEN ROW(1,2) ELSE ROW(2,1) END;
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'case'
|
||||
SELECT CASE TRUE WHEN TRUE THEN ROW(1,2) ELSE NULL END;
|
||||
ERROR HY000: Illegal parameter data types row and null for operation 'case'
|
||||
SELECT CASE TRUE WHEN TRUE THEN NULL ELSE ROW(2,1) END;
|
||||
ERROR HY000: Illegal parameter data types null and row for operation 'case'
|
||||
SELECT CASE TRUE WHEN TRUE THEN ROW(2,1) END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'case'
|
||||
SELECT CASE ROW(1,2) WHEN ROW(1,2) THEN 0 END;
|
||||
ERROR HY000: Illegal parameter data type row for operation 'CASE WHEN'
|
||||
SELECT CASE NULL WHEN ROW(1,2) THEN 0 END;
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
SELECT CASE ROW(1,2) WHEN NULL THEN 0 END;
|
||||
ERROR 21000: Operand should contain 2 column(s)
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/ROW(1,2), /*else*/ROW(2,1));
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'decode'
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/ROW(1,2), /*else*/NULL);
|
||||
ERROR HY000: Illegal parameter data types row and null for operation 'decode'
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/NULL, /*else*/ROW(2,1));
|
||||
ERROR HY000: Illegal parameter data types null and row for operation 'decode'
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/ROW(2,1));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'decode'
|
||||
SELECT oracle_schema.DECODE(/*predicant*/ROW(1,2), /*when1*/ROW(1,2), /*then1*/0);
|
||||
ERROR HY000: Illegal parameter data type row for operation 'CASE WHEN'
|
||||
SELECT oracle_schema.DECODE(/*predicant*/NULL, /*when1*/ROW(1,2), /*then1*/0);
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
SELECT oracle_schema.DECODE(/*predicant*/ROW(1,2), /*when1*/NULL, /*then1*/0);
|
||||
ERROR 21000: Operand should contain 2 column(s)
|
||||
SELECT IF(0, ROW(1,2), ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'if'
|
||||
SELECT IF(0, NULL, ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'if'
|
||||
SELECT IF(0, ROW(1,2), NULL);
|
||||
ERROR HY000: Illegal parameter data type row for operation 'if'
|
||||
SELECT NVL2('0', ROW(1,2), ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'nvl2'
|
||||
SELECT NVL2('0', NULL, ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'nvl2'
|
||||
SELECT NVL2('0', ROW(1,2), NULL);
|
||||
ERROR HY000: Illegal parameter data type row for operation 'nvl2'
|
||||
SELECT NVL2(NULL, ROW(1,2), ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'nvl2'
|
||||
SELECT NVL2(NULL, NULL, ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'nvl2'
|
||||
SELECT NVL2(NULL, ROW(1,2), NULL);
|
||||
ERROR HY000: Illegal parameter data type row for operation 'nvl2'
|
||||
SELECT COALESCE(ROW(1,2), ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'coalesce'
|
||||
SELECT COALESCE(ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'coalesce'
|
||||
SELECT COALESCE(ROW(1,2),NULL);
|
||||
ERROR HY000: Illegal parameter data types row and null for operation 'coalesce'
|
||||
SELECT COALESCE(NULL,ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types null and row for operation 'coalesce'
|
||||
SELECT IFNULL(ROW(1,2), ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types row and row for operation 'ifnull'
|
||||
SELECT IFNULL(NULL, ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data types null and row for operation 'ifnull'
|
||||
SELECT IFNULL(ROW(1,2), NULL);
|
||||
ERROR HY000: Illegal parameter data types row and null for operation 'ifnull'
|
||||
SELECT NULLIF(ROW(1,2), ROW(1,2));
|
||||
ERROR HY000: Illegal parameter data type row for operation 'nullif'
|
||||
SELECT NULLIF(NULL, ROW(1,2));
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
SELECT NULLIF(ROW(1,2), NULL);
|
||||
ERROR HY000: Illegal parameter data type row for operation 'nullif'
|
||||
# End of 12.0 tests
|
||||
|
@ -416,3 +416,114 @@ DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # End of 10.3 test
|
||||
--echo #
|
||||
|
||||
|
||||
--echo # Start of 12.0 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36716 A case expression with ROW arguments in THEN crashes
|
||||
--echo #
|
||||
|
||||
# Searched CASE + an error in THEN/ELSE arguments
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT CASE WHEN TRUE THEN ROW(1,2) ELSE ROW(2,1) END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT CASE WHEN TRUE THEN ROW(1,2) ELSE NULL END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT CASE WHEN TRUE THEN NULL ELSE ROW(2,1) END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE WHEN TRUE THEN ROW(2,1) END;
|
||||
|
||||
# Searched CASE + an error in WHEN arguments
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE WHEN ROW(1,2) THEN 0 WHEN ROW(2,1) THEN 1 END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE WHEN ROW(1,2) THEN 0 END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE WHEN NULL THEN 0 WHEN ROW(1,2) THEN 0 END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE WHEN ROW(1,2) THEN 0 WHEN NULL THEN 0 END;
|
||||
|
||||
# Simple CASE + an error in THEN arguments
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT CASE TRUE WHEN TRUE THEN ROW(1,2) ELSE ROW(2,1) END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT CASE TRUE WHEN TRUE THEN ROW(1,2) ELSE NULL END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT CASE TRUE WHEN TRUE THEN NULL ELSE ROW(2,1) END;
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE TRUE WHEN TRUE THEN ROW(2,1) END;
|
||||
|
||||
# Simple CASE + an error in WHEN arguments - rows are not supported yet
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT CASE ROW(1,2) WHEN ROW(1,2) THEN 0 END;
|
||||
--error ER_OPERAND_COLUMNS
|
||||
SELECT CASE NULL WHEN ROW(1,2) THEN 0 END;
|
||||
--error ER_OPERAND_COLUMNS
|
||||
SELECT CASE ROW(1,2) WHEN NULL THEN 0 END;
|
||||
|
||||
# oracle_schema.DECODE + an error in THEN arguments
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/ROW(1,2), /*else*/ROW(2,1));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/ROW(1,2), /*else*/NULL);
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/NULL, /*else*/ROW(2,1));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT oracle_schema.DECODE(TRUE, TRUE, /*then1*/ROW(2,1));
|
||||
|
||||
# oracle_schema.DECODE + an error in WHEN arguments - rows are not supported yet
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT oracle_schema.DECODE(/*predicant*/ROW(1,2), /*when1*/ROW(1,2), /*then1*/0);
|
||||
--error ER_OPERAND_COLUMNS
|
||||
SELECT oracle_schema.DECODE(/*predicant*/NULL, /*when1*/ROW(1,2), /*then1*/0);
|
||||
--error ER_OPERAND_COLUMNS
|
||||
SELECT oracle_schema.DECODE(/*predicant*/ROW(1,2), /*when1*/NULL, /*then1*/0);
|
||||
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT IF(0, ROW(1,2), ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT IF(0, NULL, ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT IF(0, ROW(1,2), NULL);
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT NVL2('0', ROW(1,2), ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT NVL2('0', NULL, ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT NVL2('0', ROW(1,2), NULL);
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT NVL2(NULL, ROW(1,2), ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT NVL2(NULL, NULL, ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT NVL2(NULL, ROW(1,2), NULL);
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT COALESCE(ROW(1,2), ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT COALESCE(ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT COALESCE(ROW(1,2),NULL);
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT COALESCE(NULL,ROW(1,2));
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT IFNULL(ROW(1,2), ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT IFNULL(NULL, ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||
SELECT IFNULL(ROW(1,2), NULL);
|
||||
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT NULLIF(ROW(1,2), ROW(1,2));
|
||||
--error ER_OPERAND_COLUMNS
|
||||
SELECT NULLIF(NULL, ROW(1,2));
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
SELECT NULLIF(ROW(1,2), NULL);
|
||||
|
||||
|
||||
--echo # End of 12.0 tests
|
||||
|
@ -159,7 +159,7 @@ SELECT COALESCE(a);
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
ERROR HY000: Illegal parameter data type row for operation 'coalesce'
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
@ -168,7 +168,7 @@ SELECT COALESCE(a);
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
ERROR HY000: Illegal parameter data type row for operation 'coalesce'
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
|
@ -204,7 +204,7 @@ BEGIN
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--error ER_OPERAND_COLUMNS
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
@ -217,7 +217,7 @@ BEGIN
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--error ER_OPERAND_COLUMNS
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
@ -175,7 +175,7 @@ SELECT COALESCE(a);
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
ERROR HY000: Illegal parameter data type row for operation 'coalesce'
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1()
|
||||
AS
|
||||
@ -185,7 +185,7 @@ SELECT COALESCE(a);
|
||||
END;
|
||||
$$
|
||||
CALL p1();
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
ERROR HY000: Illegal parameter data type row for operation 'coalesce'
|
||||
DROP PROCEDURE p1;
|
||||
CREATE PROCEDURE p1()
|
||||
AS
|
||||
|
@ -221,7 +221,7 @@ BEGIN
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--error ER_OPERAND_COLUMNS
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
@ -235,7 +235,7 @@ BEGIN
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
--error ER_OPERAND_COLUMNS
|
||||
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
|
||||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
|
@ -2719,6 +2719,17 @@ void Item_func_nullif::update_used_tables()
|
||||
bool
|
||||
Item_func_nullif::fix_length_and_dec(THD *thd)
|
||||
{
|
||||
/*
|
||||
The returned data type is determined only by args[0].
|
||||
Check it here to be a valid returned type for a hybrid function.
|
||||
args[1] will be checked below, to be comparable to args[0],
|
||||
its data type does not affect the returned data type.
|
||||
*/
|
||||
if (args[0]->type_handler()->
|
||||
Item_hybrid_func_fix_attributes(current_thd, func_name_cstring(),
|
||||
this, this, &args[0], 1))
|
||||
return true;
|
||||
|
||||
/*
|
||||
If this is the first invocation of fix_length_and_dec(), create the
|
||||
third argument as a copy of the first. This cannot be done before
|
||||
@ -3442,6 +3453,14 @@ bool Item_func_case_simple::aggregate_switch_and_when_arguments(THD *thd,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_found_types & (1U << ROW_RESULT))
|
||||
{
|
||||
// ROWs are not supported yet in CASE ROW(..) WHEN ROW(..)
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
|
||||
type_handler_row.name().ptr(), "CASE WHEN");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (make_unique_cmp_items(thd, cmp_collation.collation))
|
||||
return true;
|
||||
|
||||
|
@ -1226,26 +1226,33 @@ protected:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void cache_type_info(const Item *source, bool maybe_null_arg)
|
||||
bool cache_type_info(THD *thd, Item *source, bool maybe_null_arg)
|
||||
{
|
||||
if (source->type_handler()->
|
||||
Item_hybrid_func_fix_attributes(thd, func_name_cstring(),
|
||||
this, this, &source, 1))
|
||||
return true;
|
||||
Type_std_attributes::set(source);
|
||||
set_handler(source->type_handler());
|
||||
set_maybe_null(maybe_null_arg);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fix_length_and_dec2_eliminate_null(Item **items)
|
||||
bool fix_length_and_dec2_eliminate_null(THD *thd, Item **items)
|
||||
{
|
||||
// Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
|
||||
if (items[0]->type() == NULL_ITEM)
|
||||
{
|
||||
cache_type_info(items[1], true);
|
||||
if (cache_type_info(thd, items[1], true))
|
||||
return true;
|
||||
// If both arguments are NULL, make resulting type BINARY(0).
|
||||
if (items[1]->type() == NULL_ITEM)
|
||||
set_handler(&type_handler_string);
|
||||
}
|
||||
else if (items[1]->type() == NULL_ITEM)
|
||||
{
|
||||
cache_type_info(items[0], true);
|
||||
if (cache_type_info(thd, items[0], true))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1315,6 +1322,8 @@ public:
|
||||
*/
|
||||
class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2
|
||||
{
|
||||
bool check_arguments() const override
|
||||
{ return check_argument_types_can_return_bool(0, 1); }
|
||||
protected:
|
||||
virtual Item *find_item() const= 0;
|
||||
|
||||
@ -1362,8 +1371,6 @@ public:
|
||||
|
||||
class Item_func_if :public Item_func_case_abbreviation2_switch
|
||||
{
|
||||
bool check_arguments() const override
|
||||
{ return check_argument_types_can_return_bool(0, 1); }
|
||||
protected:
|
||||
Item *find_item() const override
|
||||
{ return args[0]->val_bool() ? args[1] : args[2]; }
|
||||
@ -1375,7 +1382,7 @@ public:
|
||||
bool fix_fields(THD *, Item **) override;
|
||||
bool fix_length_and_dec(THD *thd) override
|
||||
{
|
||||
return fix_length_and_dec2_eliminate_null(args + 1);
|
||||
return fix_length_and_dec2_eliminate_null(thd, args + 1);
|
||||
}
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
@ -1387,8 +1394,6 @@ public:
|
||||
override;
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_if>(thd, this); }
|
||||
private:
|
||||
void cache_type_info(Item *source);
|
||||
};
|
||||
|
||||
|
||||
@ -1409,7 +1414,7 @@ public:
|
||||
}
|
||||
bool fix_length_and_dec(THD *thd) override
|
||||
{
|
||||
return fix_length_and_dec2_eliminate_null(args + 1);
|
||||
return fix_length_and_dec2_eliminate_null(thd, args + 1);
|
||||
}
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_nvl2>(thd, this); }
|
||||
|
@ -1104,6 +1104,15 @@ public:
|
||||
*/
|
||||
class Item_func_case_expression: public Item_func_hybrid_field_type
|
||||
{
|
||||
bool check_arguments() const override
|
||||
{
|
||||
/*
|
||||
Arguments to CASE-style expressions are subject to aggregate_for_result()
|
||||
and/or aggregate_for_comparision(). These methods validate the arguments.
|
||||
No needs to check arguments here.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
public:
|
||||
Item_func_case_expression(THD *thd)
|
||||
:Item_func_hybrid_field_type(thd)
|
||||
|
@ -232,8 +232,13 @@ public:
|
||||
const Type_handler *b)
|
||||
const override
|
||||
{
|
||||
DBUG_ASSERT(a == &type_handler_row);
|
||||
DBUG_ASSERT(b == &type_handler_row);
|
||||
/*
|
||||
Allowed combinations:
|
||||
ROW+ROW, NULL+ROW, ROW+NULL
|
||||
*/
|
||||
DBUG_ASSERT(a == &type_handler_row || a == &type_handler_null);
|
||||
DBUG_ASSERT(b == &type_handler_row || b == &type_handler_null);
|
||||
DBUG_ASSERT(a == &type_handler_row || b == &type_handler_row);
|
||||
return &type_handler_row;
|
||||
}
|
||||
const Type_handler *aggregate_for_min_max(const Type_handler *a,
|
||||
@ -1893,19 +1898,16 @@ aggregate_for_result(const LEX_CSTRING &funcname, Item **items, uint nitems,
|
||||
bool treat_bit_as_number)
|
||||
{
|
||||
bool bit_and_non_bit_mixture_found= false;
|
||||
uint32 max_display_length;
|
||||
if (!nitems || items[0]->result_type() == ROW_RESULT)
|
||||
if (!nitems)
|
||||
{
|
||||
DBUG_ASSERT(0);
|
||||
set_handler(&type_handler_null);
|
||||
return true;
|
||||
}
|
||||
set_handler(items[0]->type_handler());
|
||||
max_display_length= items[0]->max_display_length();
|
||||
for (uint i= 1 ; i < nitems ; i++)
|
||||
{
|
||||
const Type_handler *cur= items[i]->type_handler();
|
||||
set_if_bigger(max_display_length, items[i]->max_display_length());
|
||||
uint bit_count= (type_handler() == &type_handler_bit) +
|
||||
(cur == &type_handler_bit);
|
||||
uint null_count= (type_handler() == &type_handler_null) +
|
||||
@ -1926,7 +1928,12 @@ aggregate_for_result(const LEX_CSTRING &funcname, Item **items, uint nitems,
|
||||
}
|
||||
}
|
||||
if (bit_and_non_bit_mixture_found && type_handler() == &type_handler_slonglong)
|
||||
{
|
||||
uint32 max_display_length= items[0]->max_display_length();
|
||||
for (uint i= 1; i < nitems ; i++)
|
||||
set_if_bigger(max_display_length, items[i]->max_display_length());
|
||||
set_handler(Type_handler::bit_and_int_mixture_handler(max_display_length));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4899,6 +4906,20 @@ bool Type_handler_timestamp_common::
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_row::
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const LEX_CSTRING &opname,
|
||||
Type_handler_hybrid_field_type *,
|
||||
Type_all_attributes *atrr,
|
||||
Item **items, uint nitems)
|
||||
const
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
|
||||
name().ptr(), opname.str);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool Type_handler::
|
||||
|
@ -4937,11 +4937,7 @@ public:
|
||||
Type_handler_hybrid_field_type *,
|
||||
Type_all_attributes *atrr,
|
||||
Item **items, uint nitems)
|
||||
const override
|
||||
{
|
||||
MY_ASSERT_UNREACHABLE();
|
||||
return true;
|
||||
}
|
||||
const override;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const override
|
||||
{
|
||||
MY_ASSERT_UNREACHABLE();
|
||||
|
Loading…
x
Reference in New Issue
Block a user