Commit 335e842d authored by Gleb Shchepa's avatar Gleb Shchepa

Bug #41363: crash of mysqld on windows with aggregate in case

Execution of queries containing the CASE function of
aggregate function like in "SELECT ... CASE ARGV(...) WHEN ..."
crashed the server.


The CASE function caches pointers to concrete comparison
functions for an each pair of types of CASE-WHERE clause
parameters, i.e. for the "CASE INT_RESULT WHERE REAL_RESULT
THEN ... WHERE DECIMAL_RESULT ... END" function call it
caches comparisons for INT_RESULT with REAL_RESULT and
for INT_RESULT with DECIMAL_RESULT. Usually a result
type is known after a call to the fix_fields function,
however, the setup_copy_fields function call may
wrap aggregate items with Item_copy_string that has
STRING_RESULT result type, so setup_copy_fields may
change argument result types of the CASE function after
call to Item_func_case::fix_fields/fix_length_and_dec.
Then the Item_func_case::find_item function tries to
use comparison function for unexpected pair of the
STRING_RESULT and some other type - that caused
an assertion failure of server crash.

The Item_func_case::fix_length_and_dec function has
been modified to take into account possible STRING_RESULT
result type in the presence of aggregate arguments of
the CASE function.


mysql-test/r/func_in.result:
  Added test case for bug #41363.
mysql-test/t/func_in.test:
  Added test case for bug #41363.
sql/item_cmpfunc.cc:
  Bug #41363: crash of mysqld on windows with aggregate in case
  
  The Item_func_case::fix_length_and_dec function has
  been modified to take into account possible STRING_RESULT
  result type in the presence of aggregate arguments of
  the CASE function.
parent 5185e921
......@@ -575,4 +575,16 @@ id
select * from t1 where NOT id in (null, 1);
id
drop table t1;
CREATE TABLE t1(c0 INTEGER, c1 INTEGER, c2 INTEGER);
INSERT INTO t1 VALUES(1, 1, 1), (1, 1, 1);
SELECT CASE AVG (c0) WHEN c1 * c2 THEN 1 END FROM t1;
CASE AVG (c0) WHEN c1 * c2 THEN 1 END
1
SELECT CASE c1 * c2 WHEN SUM(c0) THEN 1 WHEN AVG(c0) THEN 2 END FROM t1;
CASE c1 * c2 WHEN SUM(c0) THEN 1 WHEN AVG(c0) THEN 2 END
2
SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1;
CASE c1 WHEN c1 + 1 THEN 1 END ABS(AVG(c0))
NULL 1.0000
DROP TABLE t1;
End of 5.1 tests
......@@ -426,4 +426,17 @@ select * from t1 where NOT id in (select null union all select 1);
select * from t1 where NOT id in (null, 1);
drop table t1;
#
# Bug #41363: crash of mysqld on windows with aggregate in case
#
CREATE TABLE t1(c0 INTEGER, c1 INTEGER, c2 INTEGER);
INSERT INTO t1 VALUES(1, 1, 1), (1, 1, 1);
SELECT CASE AVG (c0) WHEN c1 * c2 THEN 1 END FROM t1;
SELECT CASE c1 * c2 WHEN SUM(c0) THEN 1 WHEN AVG(c0) THEN 2 END FROM t1;
SELECT CASE c1 WHEN c1 + 1 THEN 1 END, ABS(AVG(c0)) FROM t1;
DROP TABLE t1;
--echo End of 5.1 tests
......@@ -2713,6 +2713,16 @@ void Item_func_case::fix_length_and_dec()
nagg++;
if (!(found_types= collect_cmp_types(agg, nagg)))
return;
if (with_sum_func || current_thd->lex->current_select->group_list.elements)
{
/*
See TODO commentary in the setup_copy_fields function:
item in a group may be wrapped with an Item_copy_string item.
That item has a STRING_RESULT result type, so we need
to take this type into account.
*/
found_types |= (1 << item_cmp_type(left_result_type, STRING_RESULT));
}
for (i= 0; i <= (uint)DECIMAL_RESULT; i++)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment