mirror of
https://github.com/MariaDB/server.git
synced 2025-05-08 15:01:49 +03:00
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.
This commit is contained in:
parent
91fc90c372
commit
29705a4d38
@ -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;
|
|||||||
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;
|
||||||
|
|
||||||
|
33
sql/item.cc
33
sql/item.cc
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user