[Commits] ad68ee6035c: MDEV-20468: Allocating more space than required for JOIN_TAB array for a query with SJM table
revision-id: ad68ee6035c187ffcf9a2d8fbe4a2f4d670b5a52 (mariadb-10.4.7-49-gad68ee6035c) parent(s): b1e377997e987b66c999713bdb7e6cfdb87797ae author: Varun Gupta committer: Varun Gupta timestamp: 2019-09-02 19:07:25 +0530 message: MDEV-20468: Allocating more space than required for JOIN_TAB array for a query with SJM table --- sql/opt_subselect.cc | 33 +++++++++++++++++++++++++++++++++ sql/opt_subselect.h | 1 + sql/sql_select.cc | 15 ++++++++------- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index e0873185461..86f9c27ae9e 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -3926,6 +3926,39 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) } +/* + Return the number of tables at the top-level of the JOIN + + SYNOPSIS + get_number_of_tables_at_top_level() + join The join with the picked join order + + DESCRIPTION + The number of tables in the JOIN currently include all the inner tables of the + mergeable semi-joins. The function would make sure that we only count the semi-join + nest and not the inner tables of teh semi-join nest. +*/ + +uint get_number_of_tables_at_top_level(JOIN *join) +{ + uint j= 0, tables= 0; + while(j < join->table_count) + { + POSITION *cur_pos= &join->best_positions[j]; + tables++; + if (cur_pos->sj_strategy == SJ_OPT_MATERIALIZE || + cur_pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN) + { + SJ_MATERIALIZATION_INFO *sjm= cur_pos->table->emb_sj_nest->sj_mat_info; + j= j + sjm->tables; + } + else + j++; + } + return tables; +} + + /* Setup semi-join materialization strategy for one semi-join nest diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 6210fc972c8..a0dbda360f0 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -319,6 +319,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join); bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab); bool setup_sj_materialization_part2(JOIN_TAB *sjm_tab); +uint get_number_of_tables_at_top_level(JOIN *join); /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bd6d9852f40..bfcd0ee414f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3597,7 +3597,7 @@ bool JOIN::make_aggr_tables_info() unit->select_limit_cnt == 1 (we only need one row in the result set) */ sort_tab->filesort->limit= - (has_group_by || (join_tab + table_count > curr_tab + 1)) ? + (has_group_by || (join_tab + top_join_tab_count > curr_tab + 1)) ? select_limit : unit->select_limit_cnt; } if (!only_const_tables() && @@ -10162,14 +10162,16 @@ bool JOIN::get_best_combination() if (aggr_tables > 2) aggr_tables= 2; - if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)* - (top_join_tab_count + aggr_tables)))) - DBUG_RETURN(TRUE); full_join=0; hash_join= FALSE; fix_semijoin_strategies_for_picked_join_order(this); + top_join_tab_count= get_number_of_tables_at_top_level(this); + + if (!(join_tab= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)* + (top_join_tab_count + aggr_tables)))) + DBUG_RETURN(TRUE); JOIN_TAB_RANGE *root_range; if (!(root_range= new (thd->mem_root) JOIN_TAB_RANGE)) @@ -13878,7 +13880,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, ORDER BY and GROUP BY */ for (JOIN_TAB *tab= join->join_tab + join->const_tables; - tab < join->join_tab + join->table_count; + tab < join->join_tab + join->top_join_tab_count; tab++) tab->cached_eq_ref_table= FALSE; @@ -19615,8 +19617,7 @@ do_select(JOIN *join, Procedure *procedure) if (join->pushdown_query->store_data_in_temp_table) { - JOIN_TAB *last_tab= join->join_tab + join->table_count - - join->exec_join_tab_cnt(); + JOIN_TAB *last_tab= join->join_tab + join->exec_join_tab_cnt(); last_tab->next_select= end_send; enum_nested_loop_state state= last_tab->aggr->end_send();
participants (1)
-
Varun