Skip to content

Commit 4fe6fbb

Browse files
committed
Merge branch 'bb-10.2-mdev9543' of github.com:MariaDB/server into bb-10.2-mdev9543
2 parents 2bd4dc3 + d146c2c commit 4fe6fbb

File tree

8 files changed

+194
-17
lines changed

8 files changed

+194
-17
lines changed

mysql-test/r/win.result

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,3 +1401,105 @@ pk c CNT
14011401
9 2 4
14021402
10 2 3
14031403
drop table t0,t1;
1404+
#
1405+
# EXPLAIN FORMAT=JSON support for window functions
1406+
#
1407+
create table t0 (a int);
1408+
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
1409+
explain format=json select rank() over (order by a) from t0;
1410+
EXPLAIN
1411+
{
1412+
"query_block": {
1413+
"select_id": 1,
1414+
"window_functions_computation": {
1415+
"temporary_table": {
1416+
"table": {
1417+
"table_name": "t0",
1418+
"access_type": "ALL",
1419+
"rows": 10,
1420+
"filtered": 100
1421+
}
1422+
}
1423+
}
1424+
}
1425+
}
1426+
create table t1 (a int, b int, c int);
1427+
insert into t1 select a,a,a from t0;
1428+
explain format=json
1429+
select
1430+
a,
1431+
rank() over (order by sum(b))
1432+
from t1
1433+
group by a;
1434+
EXPLAIN
1435+
{
1436+
"query_block": {
1437+
"select_id": 1,
1438+
"filesort": {
1439+
"window_functions_computation": {
1440+
"temporary_table": {
1441+
"table": {
1442+
"table_name": "t1",
1443+
"access_type": "ALL",
1444+
"rows": 10,
1445+
"filtered": 100
1446+
}
1447+
}
1448+
}
1449+
}
1450+
}
1451+
}
1452+
explain format=json
1453+
select
1454+
a,
1455+
rank() over (order by sum(b))
1456+
from t1
1457+
group by a
1458+
order by null;
1459+
EXPLAIN
1460+
{
1461+
"query_block": {
1462+
"select_id": 1,
1463+
"window_functions_computation": {
1464+
"temporary_table": {
1465+
"table": {
1466+
"table_name": "t1",
1467+
"access_type": "ALL",
1468+
"rows": 10,
1469+
"filtered": 100
1470+
}
1471+
}
1472+
}
1473+
}
1474+
}
1475+
#
1476+
# Check how window function works together with GROUP BY and HAVING
1477+
#
1478+
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
1479+
b MX rank() over (order by b)
1480+
3 3 1
1481+
5 5 2
1482+
7 7 3
1483+
explain format=json
1484+
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
1485+
EXPLAIN
1486+
{
1487+
"query_block": {
1488+
"select_id": 1,
1489+
"having_condition": "(MX in (3,5,7))",
1490+
"filesort": {
1491+
"window_functions_computation": {
1492+
"temporary_table": {
1493+
"table": {
1494+
"table_name": "t1",
1495+
"access_type": "ALL",
1496+
"rows": 10,
1497+
"filtered": 100
1498+
}
1499+
}
1500+
}
1501+
}
1502+
}
1503+
}
1504+
drop table t1;
1505+
drop table t0;

mysql-test/t/win.test

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,8 +924,40 @@ execute stmt;
924924

925925
drop table t0,t1;
926926

927+
--echo #
928+
--echo # EXPLAIN FORMAT=JSON support for window functions
929+
--echo #
930+
create table t0 (a int);
931+
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
932+
933+
explain format=json select rank() over (order by a) from t0;
934+
935+
create table t1 (a int, b int, c int);
936+
insert into t1 select a,a,a from t0;
937+
938+
explain format=json
939+
select
940+
a,
941+
rank() over (order by sum(b))
942+
from t1
943+
group by a;
927944

945+
explain format=json
946+
select
947+
a,
948+
rank() over (order by sum(b))
949+
from t1
950+
group by a
951+
order by null;
928952

953+
--echo #
954+
--echo # Check how window function works together with GROUP BY and HAVING
955+
--echo #
929956

957+
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
958+
explain format=json
959+
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
930960

961+
drop table t1;
962+
drop table t0;
931963

sql/sql_explain.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,9 @@ void Explain_select::print_explain_json(Explain_query *query,
884884
case AGGR_OP_REMOVE_DUPLICATES:
885885
writer->add_member("duplicate_removal").start_object();
886886
break;
887+
case AGGR_OP_WINDOW_FUNCS:
888+
writer->add_member("window_functions_computation").start_object();
889+
break;
887890
default:
888891
DBUG_ASSERT(0);
889892
}

sql/sql_explain.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ typedef enum
265265
AGGR_OP_TEMP_TABLE,
266266
AGGR_OP_FILESORT,
267267
//AGGR_OP_READ_SORTED_FILE, // need this?
268-
AGGR_OP_REMOVE_DUPLICATES
268+
AGGR_OP_REMOVE_DUPLICATES,
269+
AGGR_OP_WINDOW_FUNCS
269270
//AGGR_OP_JOIN // Need this?
270271
} enum_explain_aggr_node_type;
271272

@@ -297,6 +298,11 @@ class Explain_aggr_remove_dups : public Explain_aggr_node
297298
enum_explain_aggr_node_type get_type() { return AGGR_OP_REMOVE_DUPLICATES; }
298299
};
299300

301+
class Explain_aggr_window_funcs : public Explain_aggr_node
302+
{
303+
public:
304+
enum_explain_aggr_node_type get_type() { return AGGR_OP_WINDOW_FUNCS; }
305+
};
300306

301307
/////////////////////////////////////////////////////////////////////////////
302308

sql/sql_select.cc

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,7 +2140,6 @@ bool JOIN::make_aggr_tables_info()
21402140
All optimization is done. Check if we can use the storage engines
21412141
group by handler to evaluate the group by
21422142
*/
2143-
group_by_handler *gbh= NULL;
21442143
if (tables_list && (tmp_table_param.sum_func_count || group_list) &&
21452144
!procedure)
21462145
{
@@ -2339,14 +2338,6 @@ bool JOIN::make_aggr_tables_info()
23392338
curr_tab->fields= &tmp_fields_list1;
23402339
set_postjoin_aggr_write_func(curr_tab);
23412340

2342-
// psergey-todo: this is probably an incorrect place:
2343-
if (select_lex->window_funcs.elements)
2344-
{
2345-
curr_tab->window_funcs= new Window_funcs_computation;
2346-
if (curr_tab->window_funcs->setup(thd, &select_lex->window_funcs))
2347-
DBUG_RETURN(true);
2348-
}
2349-
23502341
tmp_table_param.func_count= 0;
23512342
tmp_table_param.field_count+= tmp_table_param.func_count;
23522343
if (sort_and_group || curr_tab->table->group)
@@ -2658,6 +2649,24 @@ bool JOIN::make_aggr_tables_info()
26582649
skip_sort_order= true;
26592650
}
26602651
}
2652+
2653+
/*
2654+
Window functions computation step should be attached to the last join_tab
2655+
that's doing aggregation.
2656+
The last join_tab reads the data from the temp. table. It also may do
2657+
- sorting
2658+
- duplicate value removal
2659+
Both of these operations are done after window function computation step.
2660+
*/
2661+
curr_tab= join_tab + top_join_tab_count + aggr_tables - 1;
2662+
if (select_lex->window_funcs.elements)
2663+
{
2664+
curr_tab->window_funcs_step= new Window_funcs_computation;
2665+
if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs,
2666+
curr_tab))
2667+
DBUG_RETURN(true);
2668+
}
2669+
26612670
fields= curr_fields_list;
26622671
// Reset before execution
26632672
set_items_ref_array(items0);
@@ -19137,7 +19146,10 @@ bool test_if_use_dynamic_range_scan(JOIN_TAB *join_tab)
1913719146
int join_init_read_record(JOIN_TAB *tab)
1913819147
{
1913919148
int error;
19140-
19149+
/*
19150+
Note: the query plan tree for the below operations is constructed in
19151+
save_agg_explain_data.
19152+
*/
1914119153
if (tab->distinct && tab->remove_duplicates()) // Remove duplicates.
1914219154
return 1;
1914319155
if (tab->filesort && tab->sort_table()) // Sort table.
@@ -24174,6 +24186,14 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
2417424186
node= new Explain_aggr_tmp_table;
2417524187
node->child= prev_node;
2417624188

24189+
if (join_tab->window_funcs_step)
24190+
{
24191+
prev_node=node;
24192+
node= new Explain_aggr_window_funcs;
24193+
node->child= prev_node;
24194+
}
24195+
24196+
/* The below matches execution in join_init_read_record() */
2417724197
if (join_tab->distinct)
2417824198
{
2417924199
prev_node= node;
@@ -25946,9 +25966,10 @@ AGGR_OP::end_send()
2594625966

2594725967
// Update ref array
2594825968
join_tab->join->set_items_ref_array(*join_tab->ref_array);
25949-
if (join_tab->window_funcs)
25969+
if (join_tab->window_funcs_step)
2595025970
{
25951-
join_tab->window_funcs->exec(join);
25971+
if (join_tab->window_funcs_step->exec(join))
25972+
return NESTED_LOOP_ERROR;
2595225973
}
2595325974

2595425975
table->reginfo.lock_type= TL_UNLOCK;

sql/sql_select.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ typedef struct st_join_table {
428428
Non-NULL value means this join_tab must do window function computation
429429
before reading.
430430
*/
431-
Window_funcs_computation* window_funcs;
431+
Window_funcs_computation* window_funcs_step;
432432

433433
/**
434434
List of topmost expressions in the select list. The *next* JOIN TAB

sql/sql_window.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1565,11 +1565,20 @@ bool Window_func_runner::exec(JOIN *join)
15651565

15661566

15671567
bool Window_funcs_computation::setup(THD *thd,
1568-
List<Item_window_func> *window_funcs)
1568+
List<Item_window_func> *window_funcs,
1569+
JOIN_TAB *tab)
15691570
{
15701571
List_iterator_fast<Item_window_func> it(*window_funcs);
15711572
Item_window_func *item_win;
15721573
Window_func_runner *runner;
1574+
1575+
SQL_SELECT *sel= NULL;
1576+
if (tab->filesort && tab->filesort->select)
1577+
{
1578+
sel= tab->filesort->select;
1579+
DBUG_ASSERT(!sel->quick);
1580+
}
1581+
15731582
// for each window function
15741583
while ((item_win= it++))
15751584
{
@@ -1579,6 +1588,8 @@ bool Window_funcs_computation::setup(THD *thd,
15791588
{
15801589
return true;
15811590
}
1591+
/* Apply the same condition that the subsequent sort will */
1592+
runner->filesort->select= sel;
15821593
win_func_runners.push_back(runner, thd->mem_root);
15831594
}
15841595
return false;

sql/sql_window.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,11 @@ class Window_func_runner : public Sql_alloc
171171
bool exec(JOIN *join);
172172

173173
void cleanup() { delete filesort; }
174-
};
175174

175+
friend class Window_funcs_computation;
176+
};
176177

178+
struct st_join_table;
177179
/*
178180
This is a "window function computation phase": a single object of this class
179181
takes care of computing all window functions in a SELECT.
@@ -187,7 +189,7 @@ class Window_funcs_computation : public Sql_alloc
187189
{
188190
List<Window_func_runner> win_func_runners;
189191
public:
190-
bool setup(THD *thd, List<Item_window_func> *window_funcs);
192+
bool setup(THD *thd, List<Item_window_func> *window_funcs, st_join_table *tab);
191193
bool exec(JOIN *join);
192194
void cleanup();
193195
};

0 commit comments

Comments
 (0)