summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/win.result49
-rw-r--r--mysql-test/t/win.test56
-rw-r--r--sql/item.cc4
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_windowfunc.cc53
-rw-r--r--sql/item_windowfunc.h48
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/sql_priv.h1
-rw-r--r--sql/sql_select.cc48
-rw-r--r--sql/sql_window.cc16
-rw-r--r--sql/sql_window.h4
-rw-r--r--sql/sql_yacc.yy4
15 files changed, 245 insertions, 52 deletions
diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result
index 2bfd3d469d4..4692a3f76cc 100644
--- a/mysql-test/r/win.result
+++ b/mysql-test/r/win.result
@@ -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
@@ -303,7 +303,7 @@ pk c
9 2
10 2
select
-pk, c,
+pk, c,
count(*) over w1 as CNT
from t1
window w1 as (partition by c order by pk
@@ -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
diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test
index 1b527a9c22e..cc01d5e678e 100644
--- a/mysql-test/t/win.test
+++ b/mysql-test/t/win.test
@@ -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;
@@ -181,7 +181,7 @@ update t1 set c=2 where pk not in (1,2,3,4);
select * from t1;
select
- pk, c,
+ pk, c,
count(*) over w1 as CNT
from t1
window w1 as (partition by c order by pk
@@ -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,
diff --git a/sql/item.cc b/sql/item.cc
index e06be995b39..68376d1a746 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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)
diff --git a/sql/item.h b/sql/item.h
index c7de001ba18..d5f0dfec033 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -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.
*/
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 152ee9fc8f6..9183fd8f81a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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();
diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc
index 251b98d3817..e204ddd8a29 100644
--- a/sql/item_windowfunc.cc
+++ b/sql/item_windowfunc.cc
@@ -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()
diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h
index 983f196a86c..ae5a153707b 100644
--- a/sql/item_windowfunc.h
+++ b/sql/item_windowfunc.h
@@ -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"; }
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 9e868fcafdf..062854d8cea 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -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
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index deeb757bdf3..5bfa062a628 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 29271bc3e12..d4acf98c5d4 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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;
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 4d62f72f571..95102c82044 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -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 */
};
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 02680b71989..ff6c4c2578d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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);
@@ -21841,13 +21860,19 @@ 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)
{
/*
diff --git a/sql/sql_window.cc b/sql/sql_window.cc
index c75b90d84d0..c189342fc91 100644
--- a/sql/sql_window.cc
+++ b/sql/sql_window.cc
@@ -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:
diff --git a/sql/sql_window.h b/sql/sql_window.h
index 361c4a7d67f..8a4dfb7630f 100644
--- a/sql/sql_window.h
+++ b/sql/sql_window.h
@@ -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 */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6af87edea75..bb939bb6994 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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;
}
;