Commit 1c6b982e authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

MDEV-12779 Oracle/DB2 Compatibility Implicit Ordering for ROW_NUMBER OVER

Users expect window functions to produce a certain ordering of rows in
the final result set. Although the standard does not require this, we
already have the filesort result done for when we computed the window
function. If there is no ORDER BY attached to the query, just keep it
till the SELECT is completely evaluated and use that to print the
result.

Update test cases as many did not take care to guarantee a stable
result.
parent dd6e74c6
This diff is collapsed.
......@@ -68,17 +68,17 @@ first_value(pk) over (order by pk desc),
last_value(pk) over (order by pk desc)
from t1;
pk first_value(pk) over (order by pk desc) last_value(pk) over (order by pk desc)
1 11 1
2 11 2
3 11 3
4 11 4
5 11 5
6 11 6
7 11 7
8 11 8
9 11 9
10 11 10
11 11 11
10 11 10
9 11 9
8 11 8
7 11 7
6 11 6
5 11 5
4 11 4
3 11 3
2 11 2
1 11 1
select pk, a, b, c, d, e,
first_value(b) over (partition by a order by pk) as fst_b,
last_value(b) over (partition by a order by pk) as lst_b,
......
......@@ -14,49 +14,49 @@ insert into t1 values
( 7 , 2, 20),
( 9 , 4, 20),
(10 , 4, 20);
select pk, a, b,
select a,
percent_rank() over (order by a),
cume_dist() over (order by a)
from t1;
pk a b percent_rank() over (order by a) cume_dist() over (order by a)
1 0 10 0.0000000000 0.2000000000
2 0 10 0.0000000000 0.2000000000
3 1 10 0.2222222222 0.4000000000
4 1 10 0.2222222222 0.4000000000
8 2 10 0.4444444444 0.8000000000
5 2 20 0.4444444444 0.8000000000
6 2 20 0.4444444444 0.8000000000
7 2 20 0.4444444444 0.8000000000
9 4 20 0.8888888889 1.0000000000
10 4 20 0.8888888889 1.0000000000
select pk, a, b,
a percent_rank() over (order by a) cume_dist() over (order by a)
0 0.0000000000 0.2000000000
0 0.0000000000 0.2000000000
1 0.2222222222 0.4000000000
1 0.2222222222 0.4000000000
2 0.4444444444 0.8000000000
2 0.4444444444 0.8000000000
2 0.4444444444 0.8000000000
2 0.4444444444 0.8000000000
4 0.8888888889 1.0000000000
4 0.8888888889 1.0000000000
select pk,
percent_rank() over (order by pk),
cume_dist() over (order by pk)
from t1 order by pk;
pk a b percent_rank() over (order by pk) cume_dist() over (order by pk)
1 0 10 0.0000000000 0.1000000000
2 0 10 0.1111111111 0.2000000000
3 1 10 0.2222222222 0.3000000000
4 1 10 0.3333333333 0.4000000000
5 2 20 0.4444444444 0.5000000000
6 2 20 0.5555555556 0.6000000000
7 2 20 0.6666666667 0.7000000000
8 2 10 0.7777777778 0.8000000000
9 4 20 0.8888888889 0.9000000000
10 4 20 1.0000000000 1.0000000000
select pk, a, b,
pk percent_rank() over (order by pk) cume_dist() over (order by pk)
1 0.0000000000 0.1000000000
2 0.1111111111 0.2000000000
3 0.2222222222 0.3000000000
4 0.3333333333 0.4000000000
5 0.4444444444 0.5000000000
6 0.5555555556 0.6000000000
7 0.6666666667 0.7000000000
8 0.7777777778 0.8000000000
9 0.8888888889 0.9000000000
10 1.0000000000 1.0000000000
select a,
percent_rank() over (partition by a order by a),
cume_dist() over (partition by a order by a)
from t1;
pk a b percent_rank() over (partition by a order by a) cume_dist() over (partition by a order by a)
1 0 10 0.0000000000 1.0000000000
2 0 10 0.0000000000 1.0000000000
3 1 10 0.0000000000 1.0000000000
4 1 10 0.0000000000 1.0000000000
8 2 10 0.0000000000 1.0000000000
5 2 20 0.0000000000 1.0000000000
6 2 20 0.0000000000 1.0000000000
7 2 20 0.0000000000 1.0000000000
9 4 20 0.0000000000 1.0000000000
10 4 20 0.0000000000 1.0000000000
a percent_rank() over (partition by a order by a) cume_dist() over (partition by a order by a)
0 0.0000000000 1.0000000000
0 0.0000000000 1.0000000000
1 0.0000000000 1.0000000000
1 0.0000000000 1.0000000000
2 0.0000000000 1.0000000000
2 0.0000000000 1.0000000000
2 0.0000000000 1.0000000000
2 0.0000000000 1.0000000000
4 0.0000000000 1.0000000000
4 0.0000000000 1.0000000000
drop table t1;
......@@ -17,34 +17,34 @@ insert into t1 values
( 7 , 2, 20),
( 9 , 4, 20),
(10 , 4, 20);
select pk, a, b, rank() over (order by a) as rank,
select a, rank() over (order by a) as rank,
dense_rank() over (order by a) as dense_rank
from t1;
pk a b rank dense_rank
1 0 10 1 1
2 0 10 1 1
3 1 10 3 2
4 1 10 3 2
8 2 10 5 3
5 2 20 5 3
6 2 20 5 3
7 2 20 5 3
9 4 20 9 4
10 4 20 9 4
select pk, a, b, rank() over (partition by b order by a) as rank,
a rank dense_rank
0 1 1
0 1 1
1 3 2
1 3 2
2 5 3
2 5 3
2 5 3
2 5 3
4 9 4
4 9 4
select a, b, rank() over (partition by b order by a) as rank,
dense_rank() over (partition by b order by a) as dense_rank
from t1;
pk a b rank dense_rank
1 0 10 1 1
2 0 10 1 1
3 1 10 3 2
4 1 10 3 2
8 2 10 5 3
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
a b rank dense_rank
0 10 1 1
0 10 1 1
1 10 3 2
1 10 3 2
2 10 5 3
2 20 1 1
2 20 1 1
2 20 1 1
4 20 4 2
4 20 4 2
drop table t1;
#
# Test with null values in the table.
......@@ -59,46 +59,49 @@ insert into t2 values (2,'b');
insert into t2 values (-1,'');
select *, rank() over (order by s1) as rank,
dense_rank() over (order by s1) as dense_rank
from t2;
from t2
order by s1, s2;
s1 s2 rank dense_rank
1 a 5 3
NULL NULL 1 1
1 NULL 5 3
NULL a 1 1
NULL c 1 1
2 b 7 4
-1 4 2
1 NULL 5 3
1 a 5 3
2 b 7 4
select *, rank() over (partition by s2 order by s1) as rank,
dense_rank() over (partition by s2 order by s1) as dense_rank
from t2;
from t2
order by s1, s2;
s1 s2 rank dense_rank
1 a 2 2
NULL NULL 1 1
1 NULL 2 2
NULL a 1 1
NULL c 1 1
2 b 1 1
-1 1 1
1 NULL 2 2
1 a 2 2
2 b 1 1
select *, rank() over (order by s2) as rank,
dense_rank() over (order by s2) as dense_rank
from t2;
from t2
order by s2, s1;
s1 s2 rank dense_rank
1 a 4 3
NULL NULL 1 1
1 NULL 1 1
-1 3 2
NULL a 4 3
NULL c 7 5
1 a 4 3
2 b 6 4
-1 3 2
NULL c 7 5
select *, rank() over (partition by s1 order by s2) as rank,
dense_rank() over (partition by s1 order by s2) as dense_rank
from t2;
s1 s2 rank dense_rank
1 a 2 2
NULL NULL 1 1
1 NULL 1 1
NULL a 2 2
NULL c 3 3
2 b 1 1
-1 1 1
1 NULL 1 1
1 a 2 2
2 b 1 1
drop table t2;
......@@ -58,7 +58,8 @@ select
pk, a, b,
row_number() over (order by a),
row_number() over (order by b)
from t1;
from t1
order by b;
drop table t1;
......@@ -391,7 +392,6 @@ insert into t3 values
(6, 2);
select
pk,
val,
count(val) over (order by val
range between current row and
......@@ -404,7 +404,6 @@ insert into t3 values
(8, 3);
select
pk,
val,
count(val) over (order by val
range between current row and
......@@ -444,7 +443,6 @@ insert into t4 values
select
part_id,
pk,
val,
count(val) over (partition by part_id
order by val
......@@ -458,7 +456,6 @@ from t4;
--echo #
select
part_id,
pk,
val,
count(val) over (partition by part_id
order by val
......@@ -469,7 +466,6 @@ from t4;
select
part_id,
pk,
val,
count(val) over (partition by part_id
order by val
......@@ -480,7 +476,6 @@ from t4;
select
part_id,
pk,
val,
count(val) over (partition by part_id
order by val
......@@ -723,7 +718,8 @@ select
count(b) over (order by a
range between 2 preceding
and 2 following) as CNT
from t1;
from t1
order by a, pk;
drop table t1;
--echo #
......@@ -1023,6 +1019,7 @@ insert into t1 values
--echo # Check using counters
flush status;
--sorted_result
select
rank() over (partition by c order by a),
rank() over (partition by c order by b)
......@@ -1030,6 +1027,7 @@ from t1;
show status like '%sort%';
flush status;
--sorted_result
select
rank() over (partition by c order by a),
rank() over (partition by c order by a)
......@@ -1101,6 +1099,7 @@ insert into t1 values
(2,2),
(3,1);
--sorted_result
select
a, b,
rank() over (order by a), rank() over (order by b),
......@@ -1192,6 +1191,7 @@ insert into t1 values (4,'a');
insert into t1 values (2,'b');
insert into t1 values (-1,'');
--sorted_result
select
*,
ROW_NUMBER() OVER (order by s1),
......@@ -1267,7 +1267,7 @@ from t1;
drop table t1;
--echo #
--echo # MDEV-10874: two window functions with ccompatible sorting
--echo # MDEV-10874: two window functions with compatible sorting
--echo #
create table t1 (
......@@ -2110,10 +2110,12 @@ SET sql_mode = 'ONLY_FULL_GROUP_BY';
SELECT name, test, score,
AVG(score) OVER (PARTITION BY test) AS average_by_test
FROM t1;
FROM t1
ORDER BY test, name;
set @@sql_mode= @save_sql_mode;
SELECT name, test, score,
AVG(score) OVER (PARTITION BY test) AS average_by_test
FROM t1;
FROM t1
ORDER BY test, name;
drop table t1;
......@@ -17,17 +17,17 @@ insert into t1 values
( 9 , 4, 20),
(10 , 4, 20);
select pk, a, b,
select a,
percent_rank() over (order by a),
cume_dist() over (order by a)
from t1;
select pk, a, b,
select pk,
percent_rank() over (order by pk),
cume_dist() over (order by pk)
from t1 order by pk;
select pk, a, b,
select a,
percent_rank() over (partition by a order by a),
cume_dist() over (partition by a order by a)
from t1;
......
......@@ -20,11 +20,11 @@ insert into t1 values
( 9 , 4, 20),
(10 , 4, 20);
select pk, a, b, rank() over (order by a) as rank,
dense_rank() over (order by a) as dense_rank
select a, rank() over (order by a) as rank,
dense_rank() over (order by a) as dense_rank
from t1;
select pk, a, b, rank() over (partition by b order by a) as rank,
dense_rank() over (partition by b order by a) as dense_rank
select a, b, rank() over (partition by b order by a) as rank,
dense_rank() over (partition by b order by a) as dense_rank
from t1;
drop table t1;
......@@ -44,13 +44,16 @@ insert into t2 values (-1,'');
select *, rank() over (order by s1) as rank,
dense_rank() over (order by s1) as dense_rank
from t2;
from t2
order by s1, s2;
select *, rank() over (partition by s2 order by s1) as rank,
dense_rank() over (partition by s2 order by s1) as dense_rank
from t2;
from t2
order by s1, s2;
select *, rank() over (order by s2) as rank,
dense_rank() over (order by s2) as dense_rank
from t2;
from t2
order by s2, s1;
select *, rank() over (partition by s1 order by s2) as rank,
dense_rank() over (partition by s1 order by s2) as dense_rank
from t2;
......
......@@ -80,9 +80,11 @@ select std(b) over (order by a rows between current row and 0 following)
from t2;
--echo # Only peers frame.
--sorted_result
select a, b, std(b) over (order by a range between 0 preceding and 0 preceding)
from t2;
--sorted_result
select a, b, std(b) over (order by a range between 0 preceding and current row)
from t2;
......@@ -90,9 +92,11 @@ from t2;
select a, b, std(b) over (order by a range between current row and 0 preceding)
from t2;
--sorted_result
select a, b, std(b) over (order by a range between current row and 0 following)
from t2;
--sorted_result
select a, b, std(b) over (order by a range between 0 following and 0 following)
from t2;
......
......@@ -353,6 +353,15 @@ int init_slave_io_cache(IO_CACHE *master, IO_CACHE *slave)
void end_slave_io_cache(IO_CACHE *cache)
{
/* Remove the cache from the next_file_user circular linked list. */
if (cache->next_file_user != cache)
{
IO_CACHE *p= cache->next_file_user;
while (p->next_file_user != cache)
p= p->next_file_user;
p->next_file_user= cache->next_file_user;
}
my_free(cache->buffer);
}
......
......@@ -26649,9 +26649,10 @@ AGGR_OP::end_send()
// Update ref array
join_tab->join->set_items_ref_array(*join_tab->ref_array);
bool keep_last_filesort_result = join_tab->filesort ? false : true;
if (join_tab->window_funcs_step)
{
if (join_tab->window_funcs_step->exec(join))
if (join_tab->window_funcs_step->exec(join, keep_last_filesort_result))
return NESTED_LOOP_ERROR;
}
......@@ -26705,6 +26706,12 @@ AGGR_OP::end_send()
}
}
if (keep_last_filesort_result)
{
delete join_tab->filesort_result;
join_tab->filesort_result= NULL;
}
// Finish rnd scn after sending records
if (join_tab->table->file->inited)
join_tab->table->file->ha_rnd_end();
......
......@@ -2751,7 +2751,7 @@ bool Window_func_runner::exec(THD *thd, TABLE *tbl, SORT_INFO *filesort_result)
}
bool Window_funcs_sort::exec(JOIN *join)
bool Window_funcs_sort::exec(JOIN *join, bool keep_filesort_result)
{
THD *thd= join->thd;
JOIN_TAB *join_tab= join->join_tab + join->total_join_tab_cnt();
......@@ -2766,8 +2766,11 @@ bool Window_funcs_sort::exec(JOIN *join)
bool is_error= runner.exec(thd, tbl, filesort_result);
delete join_tab->filesort_result;
join_tab->filesort_result= NULL;
if (!keep_filesort_result)
{
delete join_tab->filesort_result;
join_tab->filesort_result= NULL;
}
return is_error;
}
......@@ -2876,14 +2879,18 @@ bool Window_funcs_computation::setup(THD *thd,
}
bool Window_funcs_computation::exec(JOIN *join)
bool Window_funcs_computation::exec(JOIN *join, bool keep_last_filesort_result)
{
List_iterator<Window_funcs_sort> it(win_func_sorts);
Window_funcs_sort *srt;
uint counter= 0; /* Count how many sorts we've executed. */
/* Execute each sort */
while ((srt = it++))
{
if (srt->exec(join))
counter++;
bool keep_filesort_result= keep_last_filesort_result &&
counter == win_func_sorts.elements;
if (srt->exec(join, keep_filesort_result))
return true;
}
return false;
......
......@@ -195,7 +195,7 @@ class Window_funcs_sort : public Sql_alloc
public:
bool setup(THD *thd, SQL_SELECT *sel, List_iterator<Item_window_func> &it,
st_join_table *join_tab);
bool exec(JOIN *join);
bool exec(JOIN *join, bool keep_filesort_result);
void cleanup() { delete filesort; }
friend class Window_funcs_computation;
......@@ -225,7 +225,7 @@ class Window_funcs_computation : public Sql_alloc
List<Window_funcs_sort> win_func_sorts;
public:
bool setup(THD *thd, List<Item_window_func> *window_funcs, st_join_table *tab);
bool exec(JOIN *join);
bool exec(JOIN *join, bool keep_last_filesort_result);
Explain_aggr_window_funcs *save_explain_plan(MEM_ROOT *mem_root, bool is_analyze);
void cleanup();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment