diff options
author | Igor Babaev <igor@askmonty.org> | 2016-03-23 16:09:58 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2016-03-23 16:09:58 -0700 |
commit | 82cb35be11c566e4675bd14393cfa7157a280b93 (patch) | |
tree | 4f00940bf5523bf749d3b372ee0286de6143abb4 | |
parent | a74e8d36dde934b72b230b6d50b89f8e1ec034ae (diff) | |
download | mariadb-git-82cb35be11c566e4675bd14393cfa7157a280b93.tar.gz |
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.
-rw-r--r-- | mysql-test/r/win.result | 49 | ||||
-rw-r--r-- | mysql-test/t/win.test | 56 | ||||
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item.h | 1 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/item_windowfunc.cc | 53 | ||||
-rw-r--r-- | sql/item_windowfunc.h | 48 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 4 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 6 | ||||
-rw-r--r-- | sql/sql_priv.h | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 48 | ||||
-rw-r--r-- | sql/sql_window.cc | 16 | ||||
-rw-r--r-- | sql/sql_window.h | 4 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 4 |
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; } ; |