Skip to content

Commit

Permalink
Merge ../10.2-window-funcs-r10 into 10.2
Browse files Browse the repository at this point in the history
  • Loading branch information
spetrunia committed Apr 16, 2016
2 parents b532be9 + 957809b commit 9664240
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 100 deletions.
43 changes: 43 additions & 0 deletions mysql-test/r/win.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2;
drop view if exists v1;
# ########################################################################
# # Parser tests
# ########################################################################
Expand Down Expand Up @@ -1916,3 +1917,45 @@ EXPLAIN
}
}
drop table t1;
#
# MDEV-9893: Window functions with different ORDER BY lists,
# one of these lists containing an expression
#
create table t1 (s1 int, s2 char(5));
insert into t1 values (1,'a');
insert into t1 values (null,null);
insert into t1 values (3,null);
insert into t1 values (4,'a');
insert into t1 values (2,'b');
insert into t1 values (-1,'');
select
*,
ROW_NUMBER() OVER (order by s1),
CUME_DIST() OVER (order by -s1)
from t1;
s1 s2 ROW_NUMBER() OVER (order by s1) CUME_DIST() OVER (order by -s1)
1 a 3 0.8333333333
NULL NULL 1 0.1666666667
3 NULL 5 0.5000000000
4 a 6 0.3333333333
2 b 4 0.6666666667
-1 2 1.0000000000
drop table t1;
#
# MDEV-9925: Wrong result with aggregate function as a window function
#
create table t1 (i int);
insert into t1 values (1),(2);
select i, sum(i) over (partition by i) from t1;
i sum(i) over (partition by i)
1 1
2 2
drop table t1;
#
# MDEV-9922: Assertion `!join->only_const_tables() && fsort' failed in int create_sort_index
#
create view v1 as select 1 as i;
select rank() over (order by i) from v1;
rank() over (order by i)
1
drop view v1;
10 changes: 5 additions & 5 deletions mysql-test/r/win_rank.result
Expand Up @@ -40,11 +40,11 @@ pk a b rank dense_rank
3 1 10 3 2
4 1 10 3 2
8 2 10 5 3
5 2 20 1 0
6 2 20 1 0
7 2 20 1 0
9 4 20 4 1
10 4 20 4 1
5 2 20 1 1
6 2 20 1 1
7 2 20 1 1
9 4 20 4 2
10 4 20 4 2
drop table t1;
#
# Test with null values in the table.
Expand Down
38 changes: 38 additions & 0 deletions mysql-test/t/win.test
Expand Up @@ -4,6 +4,7 @@

--disable_warnings
drop table if exists t1,t2;
drop view if exists v1;
--enable_warnings

--echo # ########################################################################
Expand Down Expand Up @@ -1163,3 +1164,40 @@ select distinct rank() over (partition by part_id order by a) from t1;

drop table t1;

--echo #
--echo # MDEV-9893: Window functions with different ORDER BY lists,
--echo # one of these lists containing an expression
--echo #

create table t1 (s1 int, s2 char(5));
insert into t1 values (1,'a');
insert into t1 values (null,null);
insert into t1 values (3,null);
insert into t1 values (4,'a');
insert into t1 values (2,'b');
insert into t1 values (-1,'');

select
*,
ROW_NUMBER() OVER (order by s1),
CUME_DIST() OVER (order by -s1)
from t1;

drop table t1;


--echo #
--echo # MDEV-9925: Wrong result with aggregate function as a window function
--echo #
create table t1 (i int);
insert into t1 values (1),(2);
select i, sum(i) over (partition by i) from t1;
drop table t1;

--echo #
--echo # MDEV-9922: Assertion `!join->only_const_tables() && fsort' failed in int create_sort_index
--echo #
create view v1 as select 1 as i;
select rank() over (order by i) from v1;
drop view v1;

5 changes: 4 additions & 1 deletion sql/item_windowfunc.cc
Expand Up @@ -185,8 +185,11 @@ void Item_sum_dense_rank::setup_window_func(THD *thd, Window_spec *window_spec)

bool Item_sum_dense_rank::add()
{
if (peer_tracker.check_if_next_group())
if (peer_tracker.check_if_next_group() || first_add)
{
first_add= false;
dense_rank++;
}

return false;
}
Expand Down
22 changes: 6 additions & 16 deletions sql/item_windowfunc.h
Expand Up @@ -213,14 +213,17 @@ class Item_sum_rank: public Item_sum_int
class Item_sum_dense_rank: public Item_sum_int
{
longlong dense_rank;
bool first_add;
Group_bound_tracker peer_tracker;
public:
/*
XXX(cvicentiu) This class could potentially be implemented in the rank
class, with a switch for the DENSE case.
*/
void clear()
{
dense_rank= 0;
first_add= true;
}
bool add();
void update_field() {}
Expand All @@ -229,9 +232,8 @@ class Item_sum_dense_rank: public Item_sum_int
return dense_rank;
}

public:
Item_sum_dense_rank(THD *thd)
: Item_sum_int(thd), dense_rank(0) {}
: Item_sum_int(thd), dense_rank(0), first_add(true) {}
enum Sumfunctype sum_func () const
{
return DENSE_RANK_FUNC;
Expand Down Expand Up @@ -427,7 +429,6 @@ class Item_sum_ntile : public Item_sum_window_with_row_count
public:
Item_sum_ntile(THD* thd, Item* num_quantiles_expr) :
Item_sum_window_with_row_count(thd, num_quantiles_expr),
num_quantiles_expr_(num_quantiles_expr),
current_row_count_(0) {};

double val_real()
Expand All @@ -443,7 +444,7 @@ class Item_sum_ntile : public Item_sum_window_with_row_count
return 0;
}

longlong num_quantiles= num_quantiles_expr_->val_int();
longlong num_quantiles= get_num_quantiles();

if (num_quantiles <= 0) {
my_error(ER_INVALID_NTILE_ARGUMENT, MYF(0));
Expand Down Expand Up @@ -487,19 +488,8 @@ class Item_sum_ntile : public Item_sum_window_with_row_count
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }

bool fix_fields(THD *thd, Item **ref)
{
if (Item_sum_window_with_row_count::fix_fields(thd, ref))
return true;
// TODO-cvicentiu is ref as a parameter here ok?
if (!num_quantiles_expr_->fixed)
num_quantiles_expr_->fix_fields(thd, ref);

return false;
}

private:
Item* num_quantiles_expr_;
longlong get_num_quantiles() { return args[0]->val_int(); }
ulong current_row_count_;
};

Expand Down
8 changes: 6 additions & 2 deletions sql/sql_base.cc
Expand Up @@ -6824,6 +6824,8 @@ find_field_in_tables(THD *thd, Item_ident *item,
or as a field name without alias,
or as a field hidden by alias,
or ignoring alias)
limit How many items in the list to check
(if limit==0 then all items are to be checked)
RETURN VALUES
0 Item is not found or item is not unique,
Expand All @@ -6841,9 +6843,10 @@ Item **not_found_item= (Item**) 0x1;
Item **
find_item_in_list(Item *find, List<Item> &items, uint *counter,
find_item_error_report_type report_error,
enum_resolution_type *resolution)
enum_resolution_type *resolution, uint limit)
{
List_iterator<Item> li(items);
uint n_items= limit == 0 ? items.elements : limit;
Item **found=0, **found_unaliased= 0, *item;
const char *db_name=0;
const char *field_name=0;
Expand All @@ -6867,8 +6870,9 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
db_name= ((Item_ident*) find)->db_name;
}

for (uint i= 0; (item=li++); i++)
for (uint i= 0; i < n_items; i++)
{
item= li++;
if (field_name &&
(item->real_item()->type() == Item::FIELD_ITEM ||
((item->type() == Item::REF_ITEM) &&
Expand Down
2 changes: 1 addition & 1 deletion sql/sql_base.h
Expand Up @@ -197,7 +197,7 @@ Field *
find_field_in_table_sef(TABLE *table, const char *name);
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error,
enum_resolution_type *resolution);
enum_resolution_type *resolution, uint limit= 0);
bool setup_tables(THD *thd, Name_resolution_context *context,
List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
List<TABLE_LIST> &leaves, bool select_insert,
Expand Down
39 changes: 26 additions & 13 deletions sql/sql_select.cc
Expand Up @@ -21221,8 +21221,6 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort)
if (fsort == NULL)
fsort= tab->filesort;

// One row, no need to sort. make_tmp_tables_info should already handle this.
DBUG_ASSERT(!join->only_const_tables() && fsort);
table= tab->table;
select= fsort->select;

Expand Down Expand Up @@ -21734,6 +21732,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

@retval
FALSE if OK
Expand All @@ -21744,7 +21743,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<Item> &fields, List<Item> &all_fields,
bool is_group_field)
bool is_group_field, bool search_in_all_fields)
{
Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
Item::Type order_item_type;
Expand Down Expand Up @@ -21849,6 +21848,18 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables
thd->where);
}
}
else if (search_in_all_fields)
{
Item **found_item= find_item_in_list(order_item, all_fields, &counter,
REPORT_EXCEPT_NOT_FOUND, &resolution,
all_fields.elements - fields.elements);
if (found_item != not_found_item)
{
order->item= &ref_pointer_array[all_fields.elements-1-counter];
order->in_field_list= 0;
return FALSE;
}
}

order->in_field_list=0;
/*
Expand Down Expand Up @@ -21896,14 +21907,15 @@ 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)
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool search_in_all_fields)
{
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))
all_fields, FALSE, search_in_all_fields))
return 1;
if ((*order->item)->with_window_func && parsing_place != IN_ORDER_BY)
{
Expand All @@ -21918,18 +21930,19 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
/**
Intitialize the GROUP BY list.

@param thd Thread handler
@param ref_pointer_array We store references to all fields that was
@param thd Thread handler
@param ref_pointer_array We store references to all fields that was
not in 'fields' here.
@param fields All fields in the select part. Any item in
@param fields All fields in the select part. Any item in
'order' that is part of these list is replaced
by a pointer to this fields.
@param all_fields Total list of all unique fields used by the
@param all_fields Total list of all unique fields used by the
select. All items in 'order' that was not part
of fields will be added first to this list.
@param order The fields we should do GROUP BY on.
@param hidden_group_fields Pointer to flag that is set to 1 if we added
@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

@todo
change ER_WRONG_FIELD_WITH_GROUP to more detailed
Expand All @@ -21944,7 +21957,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<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields)
bool *hidden_group_fields, bool search_in_all_fields)
{
enum_parsing_place parsing_place= thd->lex->current_select->parsing_place;
*hidden_group_fields=0;
Expand All @@ -21959,7 +21972,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))
all_fields, TRUE, search_in_all_fields))
return 1;
(*ord->item)->marker= UNDEF_POS; /* Mark found */
if ((*ord->item)->with_sum_func && parsing_place == IN_GROUP_BY)
Expand Down
5 changes: 3 additions & 2 deletions sql/sql_select.h
Expand Up @@ -1942,10 +1942,11 @@ int get_quick_record(SQL_SELECT *select);
SORT_FIELD * make_unireg_sortorder(THD *thd, ORDER *order, uint *length,
SORT_FIELD *sortorder);
int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List <Item> &all_fields, ORDER *order);
List<Item> &fields, List <Item> &all_fields, ORDER *order,
bool search_in_all_fields= true);
int 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);
bool *hidden_group_fields, bool search_in_all_fields= true);
bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
Ref_ptr_array ref_pointer_array);
int join_read_key2(THD *thd, struct st_join_table *tab, TABLE *table,
Expand Down

0 comments on commit 9664240

Please sign in to comment.