Commit 29705a4d authored by Sergei Petrunia's avatar Sergei Petrunia

Window functions: handle window functions as arguments to other functions

Window functions need to have their own column in the work (temp) table,
like aggregate functions do.
They don't need val_int() -> val_int_result() conversion though, so they
should be wrapped with Item_direct_ref, not Item_aggregate_ref.
parent 91fc90c3
...@@ -1812,3 +1812,22 @@ s1 s2 X ...@@ -1812,3 +1812,22 @@ s1 s2 X
NULL a 2 NULL a 2
NULL NULL 1 NULL NULL 1
drop table t1; drop table t1;
#
# Try window functions that are not directly present in the select list
#
create table t1 (a int, b int);
insert into t1 values
(1,3),
(2,2),
(3,1);
select
rank() over (order by a) -
rank() over (order by b)
from
t1;
rank() over (order by a) -
rank() over (order by b)
0
0
0
drop table t1;
...@@ -1096,3 +1096,20 @@ select *, row_number() over (order by s1, s2) as X from t1 order by X desc; ...@@ -1096,3 +1096,20 @@ select *, row_number() over (order by s1, s2) as X from t1 order by X desc;
select *, row_number() over (order by s1, s2) as X from t1 order by X desc; select *, row_number() over (order by s1, s2) as X from t1 order by X desc;
drop table t1; drop table t1;
--echo #
--echo # Try window functions that are not directly present in the select list
--echo #
create table t1 (a int, b int);
insert into t1 values
(1,3),
(2,2),
(3,1);
select
rank() over (order by a) -
rank() over (order by b)
from
t1;
drop table t1;
...@@ -1761,6 +1761,14 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, ...@@ -1761,6 +1761,14 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
((Item_sum *) this)->ref_by) ((Item_sum *) this)->ref_by)
return; return;
} }
else if (type() == WINDOW_FUNC_ITEM)
{
/*
Skip the else part, window functions are very special functions:
they need to have their own fields in the temp. table, but they
need to be proceessed differently than regular aggregate functions
*/
}
else else
{ {
/* Not a SUM() function */ /* Not a SUM() function */
...@@ -1801,7 +1809,7 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, ...@@ -1801,7 +1809,7 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
Exception is Item_direct_view_ref which we need to convert to Exception is Item_direct_view_ref which we need to convert to
Item_ref to allow fields from view being stored in tmp table. Item_ref to allow fields from view being stored in tmp table.
*/ */
Item_aggregate_ref *item_ref; Item_ref *item_ref;
uint el= fields.elements; uint el= fields.elements;
/* /*
If this is an item_ref, get the original item If this is an item_ref, get the original item
...@@ -1811,13 +1819,24 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, ...@@ -1811,13 +1819,24 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
Item *real_itm= real_item(); Item *real_itm= real_item();
ref_pointer_array[el]= real_itm; ref_pointer_array[el]= real_itm;
if (!(item_ref= (new (thd->mem_root) if (type() == WINDOW_FUNC_ITEM)
Item_aggregate_ref(thd, {
&thd->lex->current_select->context, if (!(item_ref= (new (thd->mem_root)
&ref_pointer_array[el], 0, name)))) Item_direct_ref(thd,
return; // fatal_error is set &thd->lex->current_select->context,
&ref_pointer_array[el], 0, name))))
return; // fatal_error is set
}
else
{
if (!(item_ref= (new (thd->mem_root)
Item_aggregate_ref(thd,
&thd->lex->current_select->context,
&ref_pointer_array[el], 0, name))))
return; // fatal_error is set
}
if (type() == SUM_FUNC_ITEM) if (type() == SUM_FUNC_ITEM)
item_ref->depended_from= ((Item_sum *) this)->depended_from(); item_ref->depended_from= ((Item_sum *) this)->depended_from();
fields.push_front(real_itm); fields.push_front(real_itm);
thd->change_item_tree(ref, item_ref); thd->change_item_tree(ref, item_ref);
} }
......
...@@ -7911,7 +7911,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, ...@@ -7911,7 +7911,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
Item_window_func::split_sum_func. Item_window_func::split_sum_func.
*/ */
if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && if ((item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list) || item->type() == Item::WINDOW_FUNC_ITEM) sum_func_list) || item->with_window_func)
item->split_sum_func(thd, ref_pointer_array, *sum_func_list, item->split_sum_func(thd, ref_pointer_array, *sum_func_list,
SPLIT_SUM_SELECT); SPLIT_SUM_SELECT);
thd->lex->current_select->select_list_tables|= item->used_tables(); thd->lex->current_select->select_list_tables|= item->used_tables();
......
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