1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge branch 'bb-10.2-mdev9543' of github.com:MariaDB/server into bb-10.2-mdev9543

This commit is contained in:
Sergei Petrunia
2016-03-28 22:19:55 +03:00
8 changed files with 194 additions and 17 deletions

View File

@ -1401,3 +1401,105 @@ pk c CNT
9 2 4 9 2 4
10 2 3 10 2 3
drop table t0,t1; drop table t0,t1;
#
# EXPLAIN FORMAT=JSON support for window functions
#
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
explain format=json select rank() over (order by a) from t0;
EXPLAIN
{
"query_block": {
"select_id": 1,
"window_functions_computation": {
"temporary_table": {
"table": {
"table_name": "t0",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
create table t1 (a int, b int, c int);
insert into t1 select a,a,a from t0;
explain format=json
select
a,
rank() over (order by sum(b))
from t1
group by a;
EXPLAIN
{
"query_block": {
"select_id": 1,
"filesort": {
"window_functions_computation": {
"temporary_table": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
explain format=json
select
a,
rank() over (order by sum(b))
from t1
group by a
order by null;
EXPLAIN
{
"query_block": {
"select_id": 1,
"window_functions_computation": {
"temporary_table": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
#
# Check how window function works together with GROUP BY and HAVING
#
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
b MX rank() over (order by b)
3 3 1
5 5 2
7 7 3
explain format=json
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
EXPLAIN
{
"query_block": {
"select_id": 1,
"having_condition": "(MX in (3,5,7))",
"filesort": {
"window_functions_computation": {
"temporary_table": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
drop table t1;
drop table t0;

View File

@ -924,8 +924,40 @@ execute stmt;
drop table t0,t1; drop table t0,t1;
--echo #
--echo # EXPLAIN FORMAT=JSON support for window functions
--echo #
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
explain format=json select rank() over (order by a) from t0;
create table t1 (a int, b int, c int);
insert into t1 select a,a,a from t0;
explain format=json
select
a,
rank() over (order by sum(b))
from t1
group by a;
explain format=json
select
a,
rank() over (order by sum(b))
from t1
group by a
order by null;
--echo #
--echo # Check how window function works together with GROUP BY and HAVING
--echo #
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
explain format=json
select b,max(a) as MX, rank() over (order by b) from t1 group by b having MX in (3,5,7);
drop table t1;
drop table t0;

View File

@ -884,6 +884,9 @@ void Explain_select::print_explain_json(Explain_query *query,
case AGGR_OP_REMOVE_DUPLICATES: case AGGR_OP_REMOVE_DUPLICATES:
writer->add_member("duplicate_removal").start_object(); writer->add_member("duplicate_removal").start_object();
break; break;
case AGGR_OP_WINDOW_FUNCS:
writer->add_member("window_functions_computation").start_object();
break;
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }

View File

@ -265,7 +265,8 @@ typedef enum
AGGR_OP_TEMP_TABLE, AGGR_OP_TEMP_TABLE,
AGGR_OP_FILESORT, AGGR_OP_FILESORT,
//AGGR_OP_READ_SORTED_FILE, // need this? //AGGR_OP_READ_SORTED_FILE, // need this?
AGGR_OP_REMOVE_DUPLICATES AGGR_OP_REMOVE_DUPLICATES,
AGGR_OP_WINDOW_FUNCS
//AGGR_OP_JOIN // Need this? //AGGR_OP_JOIN // Need this?
} enum_explain_aggr_node_type; } enum_explain_aggr_node_type;
@ -297,6 +298,11 @@ public:
enum_explain_aggr_node_type get_type() { return AGGR_OP_REMOVE_DUPLICATES; } enum_explain_aggr_node_type get_type() { return AGGR_OP_REMOVE_DUPLICATES; }
}; };
class Explain_aggr_window_funcs : public Explain_aggr_node
{
public:
enum_explain_aggr_node_type get_type() { return AGGR_OP_WINDOW_FUNCS; }
};
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View File

@ -2140,7 +2140,6 @@ bool JOIN::make_aggr_tables_info()
All optimization is done. Check if we can use the storage engines All optimization is done. Check if we can use the storage engines
group by handler to evaluate the group by group by handler to evaluate the group by
*/ */
group_by_handler *gbh= NULL;
if (tables_list && (tmp_table_param.sum_func_count || group_list) && if (tables_list && (tmp_table_param.sum_func_count || group_list) &&
!procedure) !procedure)
{ {
@ -2339,14 +2338,6 @@ bool JOIN::make_aggr_tables_info()
curr_tab->fields= &tmp_fields_list1; curr_tab->fields= &tmp_fields_list1;
set_postjoin_aggr_write_func(curr_tab); set_postjoin_aggr_write_func(curr_tab);
// psergey-todo: this is probably an incorrect place:
if (select_lex->window_funcs.elements)
{
curr_tab->window_funcs= new Window_funcs_computation;
if (curr_tab->window_funcs->setup(thd, &select_lex->window_funcs))
DBUG_RETURN(true);
}
tmp_table_param.func_count= 0; tmp_table_param.func_count= 0;
tmp_table_param.field_count+= tmp_table_param.func_count; tmp_table_param.field_count+= tmp_table_param.func_count;
if (sort_and_group || curr_tab->table->group) if (sort_and_group || curr_tab->table->group)
@ -2658,6 +2649,24 @@ bool JOIN::make_aggr_tables_info()
skip_sort_order= true; skip_sort_order= true;
} }
} }
/*
Window functions computation step should be attached to the last join_tab
that's doing aggregation.
The last join_tab reads the data from the temp. table. It also may do
- sorting
- duplicate value removal
Both of these operations are done after window function computation step.
*/
curr_tab= join_tab + top_join_tab_count + aggr_tables - 1;
if (select_lex->window_funcs.elements)
{
curr_tab->window_funcs_step= new Window_funcs_computation;
if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs,
curr_tab))
DBUG_RETURN(true);
}
fields= curr_fields_list; fields= curr_fields_list;
// Reset before execution // Reset before execution
set_items_ref_array(items0); set_items_ref_array(items0);
@ -19137,7 +19146,10 @@ bool test_if_use_dynamic_range_scan(JOIN_TAB *join_tab)
int join_init_read_record(JOIN_TAB *tab) int join_init_read_record(JOIN_TAB *tab)
{ {
int error; int error;
/*
Note: the query plan tree for the below operations is constructed in
save_agg_explain_data.
*/
if (tab->distinct && tab->remove_duplicates()) // Remove duplicates. if (tab->distinct && tab->remove_duplicates()) // Remove duplicates.
return 1; return 1;
if (tab->filesort && tab->sort_table()) // Sort table. if (tab->filesort && tab->sort_table()) // Sort table.
@ -24174,6 +24186,14 @@ void save_agg_explain_data(JOIN *join, Explain_select *xpl_sel)
node= new Explain_aggr_tmp_table; node= new Explain_aggr_tmp_table;
node->child= prev_node; node->child= prev_node;
if (join_tab->window_funcs_step)
{
prev_node=node;
node= new Explain_aggr_window_funcs;
node->child= prev_node;
}
/* The below matches execution in join_init_read_record() */
if (join_tab->distinct) if (join_tab->distinct)
{ {
prev_node= node; prev_node= node;
@ -25946,9 +25966,10 @@ AGGR_OP::end_send()
// Update ref array // Update ref array
join_tab->join->set_items_ref_array(*join_tab->ref_array); join_tab->join->set_items_ref_array(*join_tab->ref_array);
if (join_tab->window_funcs) if (join_tab->window_funcs_step)
{ {
join_tab->window_funcs->exec(join); if (join_tab->window_funcs_step->exec(join))
return NESTED_LOOP_ERROR;
} }
table->reginfo.lock_type= TL_UNLOCK; table->reginfo.lock_type= TL_UNLOCK;

View File

@ -428,7 +428,7 @@ typedef struct st_join_table {
Non-NULL value means this join_tab must do window function computation Non-NULL value means this join_tab must do window function computation
before reading. before reading.
*/ */
Window_funcs_computation* window_funcs; Window_funcs_computation* window_funcs_step;
/** /**
List of topmost expressions in the select list. The *next* JOIN TAB List of topmost expressions in the select list. The *next* JOIN TAB

View File

@ -1565,11 +1565,20 @@ bool Window_func_runner::exec(JOIN *join)
bool Window_funcs_computation::setup(THD *thd, bool Window_funcs_computation::setup(THD *thd,
List<Item_window_func> *window_funcs) List<Item_window_func> *window_funcs,
JOIN_TAB *tab)
{ {
List_iterator_fast<Item_window_func> it(*window_funcs); List_iterator_fast<Item_window_func> it(*window_funcs);
Item_window_func *item_win; Item_window_func *item_win;
Window_func_runner *runner; Window_func_runner *runner;
SQL_SELECT *sel= NULL;
if (tab->filesort && tab->filesort->select)
{
sel= tab->filesort->select;
DBUG_ASSERT(!sel->quick);
}
// for each window function // for each window function
while ((item_win= it++)) while ((item_win= it++))
{ {
@ -1579,6 +1588,8 @@ bool Window_funcs_computation::setup(THD *thd,
{ {
return true; return true;
} }
/* Apply the same condition that the subsequent sort will */
runner->filesort->select= sel;
win_func_runners.push_back(runner, thd->mem_root); win_func_runners.push_back(runner, thd->mem_root);
} }
return false; return false;

View File

@ -171,9 +171,11 @@ public:
bool exec(JOIN *join); bool exec(JOIN *join);
void cleanup() { delete filesort; } void cleanup() { delete filesort; }
friend class Window_funcs_computation;
}; };
struct st_join_table;
/* /*
This is a "window function computation phase": a single object of this class This is a "window function computation phase": a single object of this class
takes care of computing all window functions in a SELECT. takes care of computing all window functions in a SELECT.
@ -187,7 +189,7 @@ class Window_funcs_computation : public Sql_alloc
{ {
List<Window_func_runner> win_func_runners; List<Window_func_runner> win_func_runners;
public: public:
bool setup(THD *thd, List<Item_window_func> *window_funcs); bool setup(THD *thd, List<Item_window_func> *window_funcs, st_join_table *tab);
bool exec(JOIN *join); bool exec(JOIN *join);
void cleanup(); void cleanup();
}; };