mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Changed the base class for Item_window_func from Item_result_field to
Item_func_or_sum. Implemented method update_used_tables for class Item_findow_func. Added the flag Item::with_window_func. Made sure that window functions could be used only in SELECT list and ORDER BY clause. Added test cases that checked different illegal placements of window functions.
This commit is contained in:
@ -12,9 +12,9 @@ select rank() from t1;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'from t1' at line 1
|
||||
# Attempt to use window function in the WHERE clause
|
||||
select * from t1 where 1=rank() over (order by a);
|
||||
ERROR HY000: Invalid use of group function
|
||||
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
||||
select * from t1 where 1>row_number() over (partition by b order by a);
|
||||
ERROR HY000: Invalid use of group function
|
||||
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
||||
drop table t1;
|
||||
# ########################################################################
|
||||
# # Functionality tests
|
||||
@ -452,6 +452,49 @@ from t1
|
||||
window w1 as (partition by c), w2 as (w1 order by pk);
|
||||
ERROR HY000: Unacceptable combination of window frame bound specifications
|
||||
select
|
||||
pk, c
|
||||
from t1 where rank() over w1 > 2
|
||||
window w1 as (partition by c order by pk);
|
||||
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
||||
select
|
||||
c, max(pk) as m
|
||||
from t1
|
||||
group by c + rank() over w1
|
||||
window w1 as (order by m);
|
||||
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r
|
||||
from t1
|
||||
group by c+r
|
||||
window w1 as (order by m);
|
||||
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r
|
||||
from t1
|
||||
group by c having c+r > 3
|
||||
window w1 as (order by m);
|
||||
ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r,
|
||||
rank() over (partition by r+1 order by m)
|
||||
from t1
|
||||
group by c
|
||||
window w1 as (order by m);
|
||||
ERROR HY000: Window function is not allowed in window specification
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r,
|
||||
rank() over (partition by m order by r)
|
||||
from t1
|
||||
group by c
|
||||
window w1 as (order by m);
|
||||
ERROR HY000: Window function is not allowed in window specification
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r, dense_rank() over w2 as dr
|
||||
from t1
|
||||
group by c
|
||||
window w1 as (order by m), w2 as (partition by r order by m);
|
||||
ERROR HY000: Window function is not allowed in window specification
|
||||
select
|
||||
pk, c,
|
||||
row_number() over (partition by c order by pk
|
||||
range between unbounded preceding and current row) as r
|
||||
|
@ -20,9 +20,9 @@ select row_number() from t1;
|
||||
select rank() from t1;
|
||||
|
||||
--echo # Attempt to use window function in the WHERE clause
|
||||
--error ER_INVALID_GROUP_FUNC_USE
|
||||
--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
select * from t1 where 1=rank() over (order by a);
|
||||
--error ER_INVALID_GROUP_FUNC_USE
|
||||
--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
select * from t1 where 1>row_number() over (partition by b order by a);
|
||||
drop table t1;
|
||||
|
||||
@ -289,6 +289,56 @@ select
|
||||
from t1
|
||||
window w1 as (partition by c), w2 as (w1 order by pk);
|
||||
|
||||
--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
select
|
||||
pk, c
|
||||
from t1 where rank() over w1 > 2
|
||||
window w1 as (partition by c order by pk);
|
||||
|
||||
--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
select
|
||||
c, max(pk) as m
|
||||
from t1
|
||||
group by c + rank() over w1
|
||||
window w1 as (order by m);
|
||||
|
||||
--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r
|
||||
from t1
|
||||
group by c+r
|
||||
window w1 as (order by m);
|
||||
|
||||
--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r
|
||||
from t1
|
||||
group by c having c+r > 3
|
||||
window w1 as (order by m);
|
||||
|
||||
--error ER_WINDOW_FUNCTION_IN_WINDOW_SPEC
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r,
|
||||
rank() over (partition by r+1 order by m)
|
||||
from t1
|
||||
group by c
|
||||
window w1 as (order by m);
|
||||
|
||||
--error ER_WINDOW_FUNCTION_IN_WINDOW_SPEC
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r,
|
||||
rank() over (partition by m order by r)
|
||||
from t1
|
||||
group by c
|
||||
window w1 as (order by m);
|
||||
|
||||
--error ER_WINDOW_FUNCTION_IN_WINDOW_SPEC
|
||||
select
|
||||
c, max(pk) as m, rank() over w1 as r, dense_rank() over w2 as dr
|
||||
from t1
|
||||
group by c
|
||||
window w1 as (order by m), w2 as (partition by r order by m);
|
||||
|
||||
--error ER_NOT_ALLOWED_WINDOW_FRAME
|
||||
select
|
||||
pk, c,
|
||||
|
@ -455,7 +455,7 @@ Item::Item(THD *thd):
|
||||
{
|
||||
DBUG_ASSERT(thd);
|
||||
marker= 0;
|
||||
maybe_null=null_value=with_sum_func=with_field=0;
|
||||
maybe_null=null_value=with_sum_func=with_window_func=with_field=0;
|
||||
in_rollup= 0;
|
||||
with_subselect= 0;
|
||||
/* Initially this item is not attached to any JOIN_TAB. */
|
||||
@ -500,6 +500,7 @@ Item::Item(THD *thd, Item *item):
|
||||
in_rollup(item->in_rollup),
|
||||
null_value(item->null_value),
|
||||
with_sum_func(item->with_sum_func),
|
||||
with_window_func(item->with_window_func),
|
||||
with_field(item->with_field),
|
||||
fixed(item->fixed),
|
||||
is_autogenerated_name(item->is_autogenerated_name),
|
||||
@ -6913,6 +6914,7 @@ void Item_ref::set_properties()
|
||||
split_sum_func() doesn't try to change the reference.
|
||||
*/
|
||||
with_sum_func= (*ref)->with_sum_func;
|
||||
with_window_func= (*ref)->with_window_func;
|
||||
with_field= (*ref)->with_field;
|
||||
fixed= 1;
|
||||
if (alias_name_used)
|
||||
|
@ -697,6 +697,7 @@ public:
|
||||
of a query with ROLLUP */
|
||||
bool null_value; /* if item is null */
|
||||
bool with_sum_func; /* True if item contains a sum func */
|
||||
bool with_window_func; /* True if item contains a window func */
|
||||
/**
|
||||
True if any item except Item_sum contains a field. Set during parsing.
|
||||
*/
|
||||
|
@ -132,6 +132,7 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
|
||||
while ((item= li++))
|
||||
{
|
||||
with_sum_func|= item->with_sum_func;
|
||||
with_window_func|= item->with_window_func;
|
||||
with_field|= item->with_field;
|
||||
}
|
||||
}
|
||||
@ -226,6 +227,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
|
||||
maybe_null=1;
|
||||
|
||||
with_sum_func= with_sum_func || item->with_sum_func;
|
||||
with_window_func= with_window_func || item->with_window_func;
|
||||
with_field= with_field || item->with_field;
|
||||
used_tables_and_const_cache_join(item);
|
||||
with_subselect|= item->has_subquery();
|
||||
|
@ -45,23 +45,52 @@ Item_window_func::resolve_window_name(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Item_window_func::update_used_tables()
|
||||
{
|
||||
used_tables_cache= 0;
|
||||
window_func()->update_used_tables();
|
||||
used_tables_cache|= window_func()->used_tables();
|
||||
for (ORDER *ord= window_spec->partition_list->first; ord; ord=ord->next)
|
||||
{
|
||||
Item *item= *ord->item;
|
||||
item->update_used_tables();
|
||||
used_tables_cache|= item->used_tables();
|
||||
}
|
||||
for (ORDER *ord= window_spec->order_list->first; ord; ord=ord->next)
|
||||
{
|
||||
Item *item= *ord->item;
|
||||
item->update_used_tables();
|
||||
used_tables_cache|= item->used_tables();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_window_func::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
|
||||
enum_parsing_place place= thd->lex->current_select->parsing_place;
|
||||
|
||||
if (!(place == SELECT_LIST || place == IN_ORDER_BY))
|
||||
{
|
||||
my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (window_name && resolve_window_name(thd))
|
||||
return true;
|
||||
|
||||
if (window_spec->window_frame && is_frame_prohibited())
|
||||
{
|
||||
my_error(ER_NOT_ALLOWED_WINDOW_FRAME, MYF(0), window_func->func_name());
|
||||
my_error(ER_NOT_ALLOWED_WINDOW_FRAME, MYF(0), window_func()->func_name());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (window_spec->order_list->elements == 0 && is_order_list_mandatory())
|
||||
{
|
||||
my_error(ER_NO_ORDER_LIST_IN_WINDOW_SPEC, MYF(0), window_func->func_name());
|
||||
my_error(ER_NO_ORDER_LIST_IN_WINDOW_SPEC, MYF(0), window_func()->func_name());
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
@ -70,13 +99,17 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
|
||||
This will substitute *this (an Item_window_func object) with Item_sum
|
||||
object. Is this the intent?
|
||||
*/
|
||||
if (window_func->fix_fields(thd, ref))
|
||||
if (window_func()->fix_fields(thd, ref))
|
||||
return true;
|
||||
|
||||
const_item_cache= false;
|
||||
with_window_func= true;
|
||||
with_sum_func= false;
|
||||
|
||||
fix_length_and_dec();
|
||||
|
||||
max_length= window_func->max_length;
|
||||
maybe_null= window_func->maybe_null;
|
||||
max_length= window_func()->max_length;
|
||||
maybe_null= window_func()->maybe_null;
|
||||
|
||||
fixed= 1;
|
||||
force_return_blank= true;
|
||||
@ -113,9 +146,9 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
|
||||
void Item_window_func::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
List<Item> &fields, uint flags)
|
||||
{
|
||||
for (uint i=0; i < window_func->argument_count(); i++)
|
||||
for (uint i=0; i < window_func()->argument_count(); i++)
|
||||
{
|
||||
Item **p_item= &window_func->arguments()[i];
|
||||
Item **p_item= &window_func()->arguments()[i];
|
||||
(*p_item)->split_sum_func2(thd, ref_pointer_array, fields, p_item, flags);
|
||||
}
|
||||
}
|
||||
@ -138,7 +171,7 @@ void Item_window_func::setup_partition_border_check(THD *thd)
|
||||
Cached_item *tmp= new_Cached_item(thd, curr->item[0], TRUE);
|
||||
partition_fields.push_back(tmp);
|
||||
}
|
||||
window_func->setup_window_func(thd, window_spec);
|
||||
window_func()->setup_window_func(thd, window_spec);
|
||||
}
|
||||
|
||||
|
||||
@ -196,9 +229,9 @@ void Item_window_func::advance_window()
|
||||
if (changed > -1)
|
||||
{
|
||||
/* Next partition */
|
||||
window_func->clear();
|
||||
window_func()->clear();
|
||||
}
|
||||
window_func->add();
|
||||
window_func()->add();
|
||||
}
|
||||
|
||||
bool Item_sum_percent_rank::add()
|
||||
|
@ -408,37 +408,40 @@ class Item_sum_cume_dist: public Item_sum_percent_rank
|
||||
};
|
||||
|
||||
|
||||
class Item_window_func : public Item_result_field
|
||||
class Item_window_func : public Item_func_or_sum
|
||||
{
|
||||
/* Window function parameters as we've got them from the parser */
|
||||
public:
|
||||
Item_sum *window_func;
|
||||
LEX_STRING *window_name;
|
||||
public:
|
||||
Window_spec *window_spec;
|
||||
|
||||
/*
|
||||
This stores the data bout the partition we're currently in.
|
||||
This stores the data about the partition we're currently in.
|
||||
advance_window() uses this to tell when we've left one partition and
|
||||
entered another.
|
||||
entered another
|
||||
*/
|
||||
List<Cached_item> partition_fields;
|
||||
public:
|
||||
Item_window_func(THD *thd, Item_sum *win_func, LEX_STRING *win_name)
|
||||
: Item_result_field(thd), window_func(win_func),
|
||||
: Item_func_or_sum(thd, (Item *) win_func),
|
||||
window_name(win_name), window_spec(NULL),
|
||||
force_return_blank(true),
|
||||
read_value_from_result_field(false) {}
|
||||
read_value_from_result_field(false) {}
|
||||
|
||||
Item_window_func(THD *thd, Item_sum *win_func, Window_spec *win_spec)
|
||||
: Item_result_field(thd), window_func(win_func),
|
||||
: Item_func_or_sum(thd, (Item *) win_func),
|
||||
window_name(NULL), window_spec(win_spec),
|
||||
force_return_blank(true),
|
||||
read_value_from_result_field(false) {}
|
||||
read_value_from_result_field(false) {}
|
||||
|
||||
Item_sum *window_func() { return (Item_sum *) args[0]; }
|
||||
|
||||
void update_used_tables();
|
||||
|
||||
bool is_frame_prohibited()
|
||||
{
|
||||
switch (window_func->sum_func()) {
|
||||
switch (window_func()->sum_func()) {
|
||||
case Item_sum::ROW_NUMBER_FUNC:
|
||||
case Item_sum::RANK_FUNC:
|
||||
case Item_sum::DENSE_RANK_FUNC:
|
||||
@ -452,7 +455,7 @@ public:
|
||||
|
||||
bool is_order_list_mandatory()
|
||||
{
|
||||
switch (window_func->sum_func()) {
|
||||
switch (window_func()->sum_func()) {
|
||||
case Item_sum::RANK_FUNC:
|
||||
case Item_sum::DENSE_RANK_FUNC:
|
||||
case Item_sum::PERCENT_RANK_FUNC:
|
||||
@ -472,7 +475,10 @@ public:
|
||||
void advance_window();
|
||||
int check_partition_bound();
|
||||
|
||||
enum_field_types field_type() const { return window_func->field_type(); }
|
||||
enum_field_types field_type() const
|
||||
{
|
||||
return ((Item_sum *) args[0])->field_type();
|
||||
}
|
||||
enum Item::Type type() const { return Item::WINDOW_FUNC_ITEM; }
|
||||
|
||||
/*
|
||||
@ -485,7 +491,7 @@ public:
|
||||
- Phase#2: executor does the scan in {PARTITION, ORDER BY} order of this
|
||||
window function. It calls appropriate methods to inform the window
|
||||
function about rows entering/leaving the window.
|
||||
It calls window_func->val_int() so that current window function value
|
||||
It calls window_func()->val_int() so that current window function value
|
||||
can be saved and stored in the temp.table.
|
||||
|
||||
- Phase#3: the temporary table is read and passed to query output.
|
||||
@ -521,8 +527,8 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
res= window_func->val_real();
|
||||
null_value= window_func->null_value;
|
||||
res= window_func()->val_real();
|
||||
null_value= window_func()->null_value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -542,8 +548,8 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
res= window_func->val_int();
|
||||
null_value= window_func->null_value;
|
||||
res= window_func()->val_int();
|
||||
null_value= window_func()->null_value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -566,8 +572,8 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
res= window_func->val_str(str);
|
||||
null_value= window_func->null_value;
|
||||
res= window_func()->val_str(str);
|
||||
null_value= window_func()->null_value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -590,8 +596,8 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
res= window_func->val_decimal(dec);
|
||||
null_value= window_func->null_value;
|
||||
res= window_func()->val_decimal(dec);
|
||||
null_value= window_func()->null_value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -600,7 +606,7 @@ public:
|
||||
List<Item> &fields, uint flags);
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals = window_func->decimals;
|
||||
decimals = window_func()->decimals;
|
||||
}
|
||||
|
||||
const char* func_name() const { return "WF"; }
|
||||
|
@ -7148,6 +7148,10 @@ ER_WINDOW_FRAME_IN_REFERENCED_WINDOW_SPEC
|
||||
eng "Referenced window specification '%s' cannot contain window frame"
|
||||
ER_BAD_COMBINATION_OF_WINDOW_FRAME_BOUND_SPECS
|
||||
eng "Unacceptable combination of window frame bound specifications"
|
||||
ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
|
||||
eng "Window function is allowed only in SELECT list and ORDER BY clause"
|
||||
ER_WINDOW_FUNCTION_IN_WINDOW_SPEC
|
||||
eng "Window function is not allowed in window specification"
|
||||
ER_NOT_ALLOWED_WINDOW_FRAME
|
||||
eng "Window frame is not allowed with '%s'"
|
||||
ER_NO_ORDER_LIST_IN_WINDOW_SPEC
|
||||
|
@ -1935,6 +1935,7 @@ void st_select_lex::init_query()
|
||||
m_non_agg_field_used= false;
|
||||
m_agg_func_used= false;
|
||||
window_specs.empty();
|
||||
window_funcs.empty();
|
||||
}
|
||||
|
||||
void st_select_lex::init_select()
|
||||
|
@ -48,6 +48,7 @@ class sys_var;
|
||||
class Item_func_match;
|
||||
class File_parser;
|
||||
class Key_part_spec;
|
||||
class Item_window_func;
|
||||
struct sql_digest_state;
|
||||
|
||||
#define ALLOC_ROOT_SET 1024
|
||||
@ -1081,6 +1082,11 @@ public:
|
||||
SQL_I_List<ORDER> win_partition_list,
|
||||
SQL_I_List<ORDER> win_order_list,
|
||||
Window_frame *win_frame);
|
||||
List<Item_window_func> window_funcs;
|
||||
bool add_window_func(Item_window_func *win_func)
|
||||
{
|
||||
return window_funcs.push_back(win_func);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_non_agg_field_used;
|
||||
|
@ -344,6 +344,7 @@ enum enum_parsing_place
|
||||
IN_WHERE,
|
||||
IN_ON,
|
||||
IN_GROUP_BY,
|
||||
IN_ORDER_BY,
|
||||
PARSING_PLACE_SIZE /* always should be the last */
|
||||
};
|
||||
|
||||
|
@ -622,14 +622,16 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
ORDER *order,
|
||||
ORDER *group,
|
||||
List<Window_spec> &win_specs,
|
||||
List<Item_window_func> &win_funcs,
|
||||
bool *hidden_group_fields,
|
||||
uint *reserved)
|
||||
{
|
||||
int res;
|
||||
enum_parsing_place save_place;
|
||||
st_select_lex *const select= thd->lex->current_select;
|
||||
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
|
||||
/*
|
||||
Need to save the value, so we can turn off only any new non_agg_field_used
|
||||
Need to stave the value, so we can turn off only any new non_agg_field_used
|
||||
additions coming from the WHERE
|
||||
*/
|
||||
const bool saved_non_agg_field_used= select->non_agg_field_used();
|
||||
@ -649,14 +651,21 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
select->set_non_agg_field_used(saved_non_agg_field_used);
|
||||
|
||||
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
|
||||
|
||||
save_place= thd->lex->current_select->parsing_place;
|
||||
thd->lex->current_select->parsing_place= IN_ORDER_BY;
|
||||
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
||||
order);
|
||||
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
|
||||
thd->lex->current_select->parsing_place= save_place;
|
||||
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
|
||||
save_place= thd->lex->current_select->parsing_place;
|
||||
thd->lex->current_select->parsing_place= IN_GROUP_BY;
|
||||
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
|
||||
group, hidden_group_fields);
|
||||
thd->lex->current_select->parsing_place= save_place;
|
||||
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
|
||||
res= res || setup_windows(thd, ref_pointer_array, tables, fields, all_fields,
|
||||
win_specs);
|
||||
win_specs, win_funcs);
|
||||
thd->lex->allow_sum_func= save_allow_sum_func;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
@ -791,14 +800,18 @@ JOIN::prepare(TABLE_LIST *tables_init,
|
||||
|
||||
ref_ptrs= ref_ptr_array_slice(0);
|
||||
|
||||
enum_parsing_place save_place= thd->lex->current_select->parsing_place;
|
||||
thd->lex->current_select->parsing_place= SELECT_LIST;
|
||||
if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ,
|
||||
&all_fields, 1))
|
||||
DBUG_RETURN(-1);
|
||||
thd->lex->current_select->parsing_place= save_place;
|
||||
|
||||
if (setup_without_group(thd, ref_ptrs, tables_list,
|
||||
select_lex->leaf_tables, fields_list,
|
||||
all_fields, &conds, order, group_list,
|
||||
select_lex->window_specs,
|
||||
select_lex->window_funcs,
|
||||
&hidden_group_fields,
|
||||
&select_lex->select_n_reserved))
|
||||
DBUG_RETURN(-1);
|
||||
@ -834,6 +847,12 @@ JOIN::prepare(TABLE_LIST *tables_init,
|
||||
if (having_fix_rc || thd->is_error())
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
thd->lex->allow_sum_func= save_allow_sum_func;
|
||||
|
||||
if (having->with_window_func)
|
||||
{
|
||||
my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int res= check_and_do_in_subquery_rewrites(this);
|
||||
@ -21842,12 +21861,18 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables
|
||||
int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &all_fields, ORDER *order)
|
||||
{
|
||||
enum_parsing_place parsing_place= thd->lex->current_select->parsing_place;
|
||||
thd->where="order clause";
|
||||
for (; order; order=order->next)
|
||||
{
|
||||
if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
|
||||
all_fields, FALSE))
|
||||
return 1;
|
||||
if ((*order->item)->with_window_func && parsing_place != IN_ORDER_BY)
|
||||
{
|
||||
my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -21884,6 +21909,7 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &all_fields, ORDER *order,
|
||||
bool *hidden_group_fields)
|
||||
{
|
||||
enum_parsing_place parsing_place= thd->lex->current_select->parsing_place;
|
||||
*hidden_group_fields=0;
|
||||
ORDER *ord;
|
||||
|
||||
@ -21893,22 +21919,26 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
||||
uint org_fields=all_fields.elements;
|
||||
|
||||
thd->where="group statement";
|
||||
enum_parsing_place save_place= thd->lex->current_select->parsing_place;
|
||||
thd->lex->current_select->parsing_place= IN_GROUP_BY;
|
||||
for (ord= order; ord; ord= ord->next)
|
||||
{
|
||||
if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields,
|
||||
all_fields, TRUE))
|
||||
return 1;
|
||||
(*ord->item)->marker= UNDEF_POS; /* Mark found */
|
||||
if ((*ord->item)->with_sum_func)
|
||||
if ((*ord->item)->with_sum_func && parsing_place == IN_GROUP_BY)
|
||||
{
|
||||
my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*ord->item)->full_name());
|
||||
return 1;
|
||||
}
|
||||
if ((*ord->item)->with_window_func)
|
||||
{
|
||||
if (parsing_place == IN_GROUP_BY)
|
||||
my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
|
||||
else
|
||||
my_error(ER_WINDOW_FUNCTION_IN_WINDOW_SPEC, MYF(0));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
thd->lex->current_select->parsing_place= save_place;
|
||||
|
||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
|
||||
{
|
||||
/*
|
||||
|
@ -83,7 +83,7 @@ Window_frame::check_frame_bounds()
|
||||
int
|
||||
setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &all_fields,
|
||||
List<Window_spec> &win_specs)
|
||||
List<Window_spec> &win_specs, List<Item_window_func> &win_funcs)
|
||||
{
|
||||
Window_spec *win_spec;
|
||||
DBUG_ENTER("setup_windows");
|
||||
@ -207,6 +207,14 @@ setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List_iterator_fast<Item_window_func> li(win_funcs);
|
||||
Item_window_func *win_func_item;
|
||||
while ((win_func_item= li++))
|
||||
{
|
||||
win_func_item->update_used_tables();
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -1289,7 +1297,7 @@ bool compute_window_func_with_frames(Item_window_func *item_win,
|
||||
Frame_cursor *top_bound;
|
||||
Frame_cursor *bottom_bound;
|
||||
|
||||
Item_sum *sum_func= item_win->window_func;
|
||||
Item_sum *sum_func= item_win->window_func();
|
||||
/* This algorithm doesn't support DISTINCT aggregator */
|
||||
sum_func->set_aggregator(Aggregator::SIMPLE_AGGREGATOR);
|
||||
|
||||
@ -1382,7 +1390,7 @@ bool compute_two_pass_window_functions(Item_window_func *item_win,
|
||||
bool first_row= true;
|
||||
clone_read_record(info, info2);
|
||||
Item_sum_window_with_context *window_func=
|
||||
static_cast<Item_sum_window_with_context *>(item_win->window_func);
|
||||
static_cast<Item_sum_window_with_context *>(item_win->window_func());
|
||||
uchar *rowid_buf= (uchar*) my_malloc(table->file->ref_length, MYF(0));
|
||||
|
||||
is_error= window_func->create_window_context();
|
||||
@ -1653,7 +1661,7 @@ bool JOIN::process_window_functions(List<Item> *curr_fields_list)
|
||||
|
||||
item_win->setup_partition_border_check(thd);
|
||||
|
||||
Item_sum::Sumfunctype type= item_win->window_func->sum_func();
|
||||
Item_sum::Sumfunctype type= item_win->window_func()->sum_func();
|
||||
switch (type) {
|
||||
case Item_sum::ROW_NUMBER_FUNC:
|
||||
case Item_sum::RANK_FUNC:
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "my_global.h"
|
||||
#include "item.h"
|
||||
|
||||
class Item_window_func;
|
||||
|
||||
/*
|
||||
Window functions module.
|
||||
|
||||
@ -130,6 +132,6 @@ class Window_def : public Window_spec
|
||||
|
||||
int setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &all_fields,
|
||||
List<Window_spec> &win_specs);
|
||||
List<Window_spec> &win_specs, List<Item_window_func> &win_funcs);
|
||||
|
||||
#endif /* SQL_WINDOW_INCLUDED */
|
||||
|
@ -10397,6 +10397,8 @@ window_func_expr:
|
||||
$$= new (thd->mem_root) Item_window_func(thd, (Item_sum *) $1, $3);
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
if (Select->add_window_func((Item_window_func *) $$))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
|
|
||||
window_func OVER_SYM window_spec
|
||||
@ -10411,6 +10413,8 @@ window_func_expr:
|
||||
thd->lex->win_spec);
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
if (Select->add_window_func((Item_window_func *) $$))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
|
Reference in New Issue
Block a user