Skip to content
Permalink
Browse files

The implementation of the template bubble_sort assumed

that the call-back comparison function returns a positive
number when arg1 < arg2, and a negative number when arg1 > arg2.
This is not in line with other implementation of sorting
algorithm.
Changed bubble_sort: now a negative result from the comparison
function means that arg1 < arg2, and positive result means
that arg1 > arg2.
Changed accordingly all call-back functions that are used as
parameters in the call of bubble_sort.

Added a test case to check the proper sorting of window functions.
  • Loading branch information...
igorbabaev committed Apr 1, 2016
1 parent c9ff5cf commit 2e4bd4407ed73b45d017ef160b2964aff1af7c6f
Showing with 202 additions and 57 deletions.
  1. +75 −0 mysql-test/r/win.result
  2. +53 −0 mysql-test/t/win.test
  3. +2 −2 sql/opt_subselect.cc
  4. +1 −1 sql/opt_table_elimination.cc
  5. +1 −1 sql/sql_list.h
  6. +24 −15 sql/sql_select.cc
  7. +46 −38 sql/sql_window.cc
@@ -1505,3 +1505,78 @@ EXPLAIN
}
drop table t1;
drop table t0;
#
# Building ordering index for window functions
#
create table t1 (
pk int primary key,
a int,
b int,
c int
);
insert into t1 values
(101 , 0, 10, 1),
(102 , 0, 10, 2),
(103 , 1, 10, 3),
(104 , 1, 10, 4),
(108 , 2, 10, 5),
(105 , 2, 20, 6),
(106 , 2, 20, 7),
(107 , 2, 20, 8),
(109 , 4, 20, 9),
(110 , 4, 20, 10),
(111 , 5, NULL, 11),
(112 , 5, 1, 12),
(113 , 5, NULL, 13),
(114 , 5, NULL, 14),
(115 , 5, NULL, 15),
(116 , 6, 1, NULL),
(117 , 6, 1, 10),
(118 , 6, 1, 1),
(119 , 6, 1, NULL),
(120 , 6, 1, NULL),
(121 , 6, 1, NULL),
(122 , 6, 1, 2),
(123 , 6, 1, 20),
(124 , 6, 1, -10),
(125 , 6, 1, NULL),
(126 , 6, 1, NULL),
(127 , 6, 1, NULL);
select sum(b) over (partition by a order by b,pk
rows between unbounded preceding and current row) as c1,
avg(b) over (w1 rows between 1 preceding and 1 following) as c2,
sum(c) over (w2 rows between 1 preceding and 1 following) as c5,
avg(b) over (w1 rows between 5 preceding and 5 following) as c3,
sum(b) over (w1 rows between 1 preceding and 1 following) as c4
from t1
window w1 as (partition by a order by b,pk),
w2 as (partition by b order by c,pk);
c1 c2 c5 c3 c4
1 1.0000 42 1.0000 1
1 1.0000 NULL 1.0000 2
10 1.0000 NULL 1.0000 3
10 10.0000 3 10.0000 20
10 10.0000 9 10.0000 20
10 15.0000 9 17.5000 30
11 1.0000 NULL 1.0000 3
12 1.0000 -10 1.0000 2
2 1.0000 24 1.0000 3
20 10.0000 12 10.0000 20
20 10.0000 6 10.0000 20
20 20.0000 27 20.0000 40
3 1.0000 -7 1.0000 3
30 16.6667 13 17.5000 50
4 1.0000 NULL 1.0000 3
40 20.0000 19 20.0000 40
5 1.0000 NULL 1.0000 3
50 20.0000 21 17.5000 60
6 1.0000 NULL 1.0000 3
7 1.0000 13 1.0000 3
70 20.0000 24 17.5000 40
8 1.0000 32 1.0000 3
9 1.0000 -9 1.0000 3
NULL 1.0000 29 1.0000 1
NULL NULL 24 1.0000 NULL
NULL NULL 38 1.0000 NULL
NULL NULL 42 1.0000 NULL
drop table t1;
@@ -961,3 +961,56 @@ select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in
drop table t1;
drop table t0;

--echo #
--echo # Building ordering index for window functions
--echo #

create table t1 (
pk int primary key,
a int,
b int,
c int
);

insert into t1 values
(101 , 0, 10, 1),
(102 , 0, 10, 2),
(103 , 1, 10, 3),
(104 , 1, 10, 4),
(108 , 2, 10, 5),
(105 , 2, 20, 6),
(106 , 2, 20, 7),
(107 , 2, 20, 8),
(109 , 4, 20, 9),
(110 , 4, 20, 10),
(111 , 5, NULL, 11),
(112 , 5, 1, 12),
(113 , 5, NULL, 13),
(114 , 5, NULL, 14),
(115 , 5, NULL, 15),
(116 , 6, 1, NULL),
(117 , 6, 1, 10),
(118 , 6, 1, 1),
(119 , 6, 1, NULL),
(120 , 6, 1, NULL),
(121 , 6, 1, NULL),
(122 , 6, 1, 2),
(123 , 6, 1, 20),
(124 , 6, 1, -10),
(125 , 6, 1, NULL),
(126 , 6, 1, NULL),
(127 , 6, 1, NULL);

--sorted_result
select sum(b) over (partition by a order by b,pk
rows between unbounded preceding and current row) as c1,
avg(b) over (w1 rows between 1 preceding and 1 following) as c2,
sum(c) over (w2 rows between 1 preceding and 1 following) as c5,
avg(b) over (w1 rows between 5 preceding and 5 following) as c3,
sum(b) over (w1 rows between 1 preceding and 1 following) as c4
from t1
window w1 as (partition by a order by b,pk),
w2 as (partition by b order by c,pk);

drop table t1;

@@ -1342,8 +1342,8 @@ static bool replace_where_subcondition(JOIN *join, Item **expr,
static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2,
void *arg)
{
return (el1->sj_convert_priority > el2->sj_convert_priority) ? 1 :
( (el1->sj_convert_priority == el2->sj_convert_priority)? 0 : -1);
return (el1->sj_convert_priority > el2->sj_convert_priority) ? -1 :
( (el1->sj_convert_priority == el2->sj_convert_priority)? 0 : 1);
}


@@ -1105,7 +1105,7 @@ int compare_field_values(Dep_value_field *a, Dep_value_field *b, void *unused)

uint b_ratio= b->field->table->tablenr*MAX_FIELDS +
b->field->field_index;
return (a_ratio < b_ratio)? -1 : ((a_ratio == b_ratio)? 0 : 1);
return (a_ratio < b_ratio)? 1 : ((a_ratio == b_ratio)? 0 : -1);
}


@@ -607,7 +607,7 @@ inline void bubble_sort(List<T> *list_to_sort,
swap= FALSE;
while ((item2= it++) && (ref2= it.ref()) != last_ref)
{
if (sort_func(item1, item2, arg) < 0)
if (sort_func(item1, item2, arg) > 0)
{
*ref1= item2;
*ref2= item1;
@@ -13274,16 +13274,16 @@ static int compare_fields_by_table_order(Item *field1,
Item_field *f1= (Item_field *) (field1->real_item());
Item_field *f2= (Item_field *) (field2->real_item());
if (field1->const_item() || f1->const_item())
return 1;
if (field2->const_item() || f2->const_item())
return -1;
if (f2->used_tables() & OUTER_REF_TABLE_BIT)
{
if (field2->const_item() || f2->const_item())
return 1;
if (f1->used_tables() & OUTER_REF_TABLE_BIT)
{
outer_ref= 1;
cmp= -1;
}
if (f1->used_tables() & OUTER_REF_TABLE_BIT)
{
if (f2->used_tables() & OUTER_REF_TABLE_BIT)
{
outer_ref= 1;
cmp++;
}
@@ -13307,10 +13307,12 @@ static int compare_fields_by_table_order(Item *field1,
tab2= tab2->bush_root_tab;
}

cmp= tab2 - tab1;
cmp= tab1 - tab2;

if (!cmp)
{
/* Fields f1, f2 belong to the same table */

JOIN_TAB *tab= idx[f1->field->table->tablenr];
uint keyno= MAX_KEY;
if (tab->ref.key_parts)
@@ -13319,31 +13321,38 @@ static int compare_fields_by_table_order(Item *field1,
keyno = tab->select->quick->index;
if (keyno != MAX_KEY)
{
if (f2->field->part_of_key.is_set(keyno))
cmp= -1;
if (f1->field->part_of_key.is_set(keyno))
cmp= -1;
if (f2->field->part_of_key.is_set(keyno))
cmp++;
/*
Here:
if both f1, f2 are components of the key tab->ref.key then cmp==0,
if only f1 is a component of the key then cmp==-1 (f1 is better),
if only f2 is a component of the key then cmp==1, (f2 is better),
if none of f1,f1 is component of the key cmp==0.
*/
if (!cmp)
{
KEY *key_info= tab->table->key_info + keyno;
for (uint i= 0; i < key_info->user_defined_key_parts; i++)
{
Field *fld= key_info->key_part[i].field;
if (fld->eq(f2->field))
if (fld->eq(f1->field))
{
cmp= -1;
cmp= -1; // f1 is better
break;
}
if (fld->eq(f1->field))
if (fld->eq(f2->field))
{
cmp= 1;
cmp= 1; // f2 is better
break;
}
}
}
}
else
cmp= f2->field->field_index-f1->field->field_index;
if (!cmp)
cmp= f1->field->field_index-f2->field->field_index;
}
return cmp < 0 ? -1 : (cmp ? 1 : 0);
}

0 comments on commit 2e4bd44

Please sign in to comment.
You can’t perform that action at this time.