From fd7accabbb4f13d54e5cabc1d20ac0d0ad237beb Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 3 Feb 2017 00:10:36 -0800 Subject: [PATCH] Fixed bug mdev-9923. Partition and order lists of a window specification cannot use constant integer to refer to select list elements. --- mysql-test/r/win.result | 25 +++++++++++++++++++++++++ mysql-test/t/win.test | 13 +++++++++++++ sql/sql_select.cc | 19 ++++++++++--------- sql/sql_select.h | 4 ++-- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 44300579411..fc215c2b793 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -2472,3 +2472,28 @@ select sum(sum(id)) over (order by sum(id)) from t1; sum(sum(id)) over (order by sum(id)) 8 drop table t1; +# +# MDEV-9923: integer constant in order by list +# of window specification +# +create table test.t1 (id int); +insert into test.t1 values (1), (2), (3), (2); +select rank() over (order by 1) from t1; +rank() over (order by 1) +1 +1 +1 +1 +select rank() over (order by 2) from t1; +rank() over (order by 2) +1 +1 +1 +1 +select rank() over (partition by id order by 2) from t1; +rank() over (partition by id order by 2) +1 +1 +1 +1 +drop table t1; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index debe5181fc0..552be3484ef 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -1504,3 +1504,16 @@ select sum(sum(id)) over (order by sum(id)) from t1; drop table t1; +--echo # +--echo # MDEV-9923: integer constant in order by list +--echo # of window specification +--echo # + +create table test.t1 (id int); +insert into test.t1 values (1), (2), (3), (2); + +select rank() over (order by 1) from t1; +select rank() over (order by 2) from t1; +select rank() over (partition by id order by 2) from t1; + +drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e1769e0979f..4b652ff74ee 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -21917,7 +21917,7 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) @param[in,out] all_fields All select, group and order by fields @param[in] is_group_field True if order is a GROUP field, false if ORDER by field - @param[in] search_in_all_fields If true then search in all_fields + @param[in] from_window_spec If true then order is from a window spec @retval FALSE if OK @@ -21928,7 +21928,7 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) static bool find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, ORDER *order, List &fields, List &all_fields, - bool is_group_field, bool search_in_all_fields) + bool is_group_field, bool from_window_spec) { Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */ Item::Type order_item_type; @@ -21941,7 +21941,8 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables Local SP variables may be int but are expressions, not positions. (And they can't be used before fix_fields is called for them). */ - if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item()) + if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item() && + !from_window_spec) { /* Order by position */ uint count; if (order->counter_used) @@ -22033,7 +22034,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables thd->where); } } - else if (search_in_all_fields) + else if (from_window_spec) { Item **found_item= find_item_in_list(order_item, all_fields, &counter, REPORT_EXCEPT_NOT_FOUND, &resolution, @@ -22093,14 +22094,14 @@ 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 &fields, List &all_fields, ORDER *order, - bool search_in_all_fields) + bool from_window_spec) { 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, search_in_all_fields)) + all_fields, FALSE, from_window_spec)) return 1; if ((*order->item)->with_window_func && parsing_place != IN_ORDER_BY) { @@ -22127,7 +22128,7 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, @param order The fields we should do GROUP/PARTITION BY on @param hidden_group_fields Pointer to flag that is set to 1 if we added any fields to all_fields. - @param search_in_all_fields If true then search in all_fields + @param from_window_spec If true then list is from a window spec @todo change ER_WRONG_FIELD_WITH_GROUP to more detailed @@ -22142,7 +22143,7 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, - bool *hidden_group_fields, bool search_in_all_fields) + bool *hidden_group_fields, bool from_window_spec) { enum_parsing_place parsing_place= thd->lex->current_select->parsing_place; *hidden_group_fields=0; @@ -22157,7 +22158,7 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, for (ord= order; ord; ord= ord->next) { if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields, - all_fields, TRUE, search_in_all_fields)) + all_fields, TRUE, from_window_spec)) return 1; (*ord->item)->marker= UNDEF_POS; /* Mark found */ if ((*ord->item)->with_sum_func && parsing_place == IN_GROUP_BY) diff --git a/sql/sql_select.h b/sql/sql_select.h index f3b59e5d20c..ab4cc89c9d3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1943,10 +1943,10 @@ int safe_index_read(JOIN_TAB *tab); int get_quick_record(SQL_SELECT *select); int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, - bool search_in_all_fields= true); + bool from_window_spec= false); int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, - bool *hidden_group_fields, bool search_in_all_fields= true); + bool *hidden_group_fields, bool from_window_spec= false); bool fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, Ref_ptr_array ref_pointer_array); int join_read_key2(THD *thd, struct st_join_table *tab, TABLE *table,