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:
Alexander Barkov 2025-04-30 14:04:43 +04:00
parent 4fc1063796
commit c5d8b9963a
11 changed files with 277 additions and 29 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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); }

View File

@ -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)

View File

@ -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::

View File

@ -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();