mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
MDEV-12851: Case with window functions query crashes server
The "is null" function performs one operation which no other Item_func does, which is to update used tables during fix_length_and_dec(). This however can not be performed before window functions have had a chance to resolve their order by and partition by definitions, which happens after the initial setup_fields call. Consequently, do not call Item_func_isnull update_used_tables during fix_length_and_dec(). There was another issue detected once the crash was resolved. Because window functions did not implement is_null() method, we would end up returning bad results for "is null" and "is not null" functions. Implemented is_null() method for Item_windowfunc.
This commit is contained in:
@@ -3097,3 +3097,33 @@ a
|
||||
300
|
||||
300
|
||||
drop table t;
|
||||
#
|
||||
# MDEV-12851 case with window functions query crashes server
|
||||
#
|
||||
create table t1(dt datetime);
|
||||
insert into t1 values ('2017-05-17'), ('2017-05-18');
|
||||
select dt,
|
||||
case when (max(dt) over (order by dt rows between 1 following and 1 following) is null)
|
||||
then '9999-12-31 12:00:00'
|
||||
else max(dt) over (order by dt rows between 1 following and 1 following)
|
||||
end x,
|
||||
case when (max(dt) over (order by dt rows between 1 following and 1 following) is not null)
|
||||
then '9999-12-31 12:00:00'
|
||||
else max(dt) over (order by dt rows between 1 following and 1 following)
|
||||
end x
|
||||
from t1;
|
||||
dt x x
|
||||
2017-05-17 00:00:00 2017-05-18 00:00:00 9999-12-31 12:00:00
|
||||
2017-05-18 00:00:00 9999-12-31 12:00:00 NULL
|
||||
drop table t1;
|
||||
create table t1(i int);
|
||||
insert into t1 values (null),(1),(2);
|
||||
select max(i) over (order by i),
|
||||
max(i) over (order by i) is null,
|
||||
max(i) over (order by i) is not null
|
||||
from t1;
|
||||
max(i) over (order by i) max(i) over (order by i) is null max(i) over (order by i) is not null
|
||||
NULL 1 0
|
||||
1 0 1
|
||||
2 0 1
|
||||
drop table t1;
|
||||
|
||||
@@ -1887,3 +1887,30 @@ insert into t values (1, 10), (2, 20), (3, 30);
|
||||
prepare stmt from "SELECT (CASE WHEN sum(t.a) over (partition by t.b)=1 THEN 1000 ELSE 300 END) AS a FROM t";
|
||||
execute stmt;
|
||||
drop table t;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12851 case with window functions query crashes server
|
||||
--echo #
|
||||
|
||||
create table t1(dt datetime);
|
||||
insert into t1 values ('2017-05-17'), ('2017-05-18');
|
||||
select dt,
|
||||
case when (max(dt) over (order by dt rows between 1 following and 1 following) is null)
|
||||
then '9999-12-31 12:00:00'
|
||||
else max(dt) over (order by dt rows between 1 following and 1 following)
|
||||
end x,
|
||||
case when (max(dt) over (order by dt rows between 1 following and 1 following) is not null)
|
||||
then '9999-12-31 12:00:00'
|
||||
else max(dt) over (order by dt rows between 1 following and 1 following)
|
||||
end x
|
||||
from t1;
|
||||
|
||||
drop table t1;
|
||||
|
||||
create table t1(i int);
|
||||
insert into t1 values (null),(1),(2);
|
||||
select max(i) over (order by i),
|
||||
max(i) over (order by i) is null,
|
||||
max(i) over (order by i) is not null
|
||||
from t1;
|
||||
drop table t1;
|
||||
|
||||
@@ -1770,11 +1770,6 @@ public:
|
||||
Item_func_isnull(THD *thd, Item *a): Item_func_null_predicate(thd, a) {}
|
||||
longlong val_int();
|
||||
enum Functype functype() const { return ISNULL_FUNC; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
Item_func_null_predicate::fix_length_and_dec();
|
||||
update_used_tables();
|
||||
}
|
||||
const char *func_name() const { return "isnull"; }
|
||||
void print(String *str, enum_query_type query_type);
|
||||
enum precedence precedence() const { return CMP_PRECEDENCE; }
|
||||
|
||||
@@ -153,8 +153,9 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
|
||||
is to allow all Item_field() objects to setup pointers to the table fields.
|
||||
|
||||
Sets as a side effect the following class variables:
|
||||
maybe_null Set if any argument may return NULL
|
||||
with_sum_func Set if any of the arguments contains a sum function
|
||||
maybe_null Set if any argument may return NULL
|
||||
with_sum_func Set if any of the arguments contains a sum function
|
||||
with_window_func Set if any of the arguments contain a window function
|
||||
with_field Set if any of the arguments contains or is a field
|
||||
used_tables_cache Set to union of the tables used by arguments
|
||||
|
||||
|
||||
@@ -848,6 +848,17 @@ public:
|
||||
read_value_from_result_field= true;
|
||||
}
|
||||
|
||||
bool is_null()
|
||||
{
|
||||
if (force_return_blank)
|
||||
return false;
|
||||
|
||||
if (read_value_from_result_field)
|
||||
return result_field->is_null();
|
||||
|
||||
return window_func()->is_null();
|
||||
}
|
||||
|
||||
double val_real()
|
||||
{
|
||||
double res;
|
||||
|
||||
Reference in New Issue
Block a user