Commit 61084a59 authored by Sergey Petrunya's avatar Sergey Petrunya

MWL#90: Address review feedback part #14

parent a585a4c5
...@@ -2316,7 +2316,7 @@ bool Item_in_subselect::init_left_expr_cache() ...@@ -2316,7 +2316,7 @@ bool Item_in_subselect::init_left_expr_cache()
An IN predicate might be evaluated in a query for which all tables have An IN predicate might be evaluated in a query for which all tables have
been optimzied away. been optimzied away.
*/ */
if (!outer_join || !outer_join->tables || !outer_join->tables_list) if (!outer_join || !outer_join->table_count || !outer_join->tables_list)
return TRUE; return TRUE;
if (!(left_expr_cache= new List<Cached_item>)) if (!(left_expr_cache= new List<Cached_item>))
...@@ -2701,9 +2701,9 @@ int subselect_single_select_engine::exec() ...@@ -2701,9 +2701,9 @@ int subselect_single_select_engine::exec()
pushed down into the subquery. Those optimizations are ref[_or_null] pushed down into the subquery. Those optimizations are ref[_or_null]
acceses. Change them to be full table scans. acceses. Change them to be full table scans.
*/ */
for (uint i=join->const_tables ; i < join->tables ; i++) for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES); tab;
tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
{ {
JOIN_TAB *tab=join->join_tab+i;
if (tab && tab->keyuse) if (tab && tab->keyuse)
{ {
for (uint i= 0; i < tab->ref.key_parts; i++) for (uint i= 0; i < tab->ref.key_parts; i++)
......
...@@ -4319,7 +4319,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records) ...@@ -4319,7 +4319,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
return 1; return 1;
*/ */
JOIN *join= param->thd->lex->select_lex.join; JOIN *join= param->thd->lex->select_lex.join;
if (!join || join->tables == 1) if (!join || join->table_count == 1)
{ {
/* No join, assume reading is done in one 'sweep' */ /* No join, assume reading is done in one 'sweep' */
result= busy_blocks*(DISK_SEEK_BASE_COST + result= busy_blocks*(DISK_SEEK_BASE_COST +
...@@ -11270,7 +11270,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) ...@@ -11270,7 +11270,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
/* Perform few 'cheap' tests whether this access method is applicable. */ /* Perform few 'cheap' tests whether this access method is applicable. */
if (!join) if (!join)
DBUG_RETURN(NULL); /* This is not a select statement. */ DBUG_RETURN(NULL); /* This is not a select statement. */
if ((join->tables != 1) || /* The query must reference one table. */ if ((join->table_count != 1) || /* The query must reference one table. */
((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */ ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
(!join->select_distinct)) || (!join->select_distinct)) ||
(join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */ (join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
......
...@@ -203,6 +203,9 @@ static bool sj_table_is_included(JOIN *join, JOIN_TAB *join_tab); ...@@ -203,6 +203,9 @@ static bool sj_table_is_included(JOIN *join, JOIN_TAB *join_tab);
static Item *remove_additional_cond(Item* conds); static Item *remove_additional_cond(Item* conds);
static void remove_subq_pushed_predicates(JOIN *join, Item **where); static void remove_subq_pushed_predicates(JOIN *join, Item **where);
enum_nested_loop_state
end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
/* /*
Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them Check if we need JOIN::prepare()-phase subquery rewrites and if yes, do them
...@@ -644,7 +647,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) ...@@ -644,7 +647,7 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
{ {
st_select_lex *child_select= (*in_subq)->get_select_lex(); st_select_lex *child_select= (*in_subq)->get_select_lex();
JOIN *child_join= child_select->join; JOIN *child_join= child_select->join;
child_join->outer_tables = child_join->tables; child_join->outer_tables = child_join->table_count;
/* /*
child_select->where contains only the WHERE predicate of the child_select->where contains only the WHERE predicate of the
...@@ -693,15 +696,15 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) ...@@ -693,15 +696,15 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
bool remove_item= TRUE; bool remove_item= TRUE;
if ((*in_subq)->is_flattenable_semijoin) if ((*in_subq)->is_flattenable_semijoin)
{ {
if (join->tables + if (join->table_count +
(*in_subq)->unit->first_select()->join->tables >= MAX_TABLES) (*in_subq)->unit->first_select()->join->table_count >= MAX_TABLES)
break; break;
if (convert_subq_to_sj(join, *in_subq)) if (convert_subq_to_sj(join, *in_subq))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
else else
{ {
if (join->tables + 1 >= MAX_TABLES) if (join->table_count + 1 >= MAX_TABLES)
break; break;
if (convert_subq_to_jtbm(join, *in_subq, &remove_item)) if (convert_subq_to_jtbm(join, *in_subq, &remove_item))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -830,7 +833,8 @@ void get_delayed_table_estimates(TABLE *table, ...@@ -830,7 +833,8 @@ void get_delayed_table_estimates(TABLE *table,
double read_time; double read_time;
/* Calculate #rows and cost of join execution */ /* Calculate #rows and cost of join execution */
get_partial_join_cost(join, join->tables - join->const_tables, &read_time, &rows); get_partial_join_cost(join, join->table_count - join->const_tables,
&read_time, &rows);
*out_rows= (ha_rows)rows; *out_rows= (ha_rows)rows;
*startup_cost= read_time; *startup_cost= read_time;
...@@ -1097,8 +1101,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) ...@@ -1097,8 +1101,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
subq_pred->exec_method= Item_in_subselect::SEMI_JOIN; // for subsequent executions subq_pred->exec_method= Item_in_subselect::SEMI_JOIN; // for subsequent executions
/*TODO: also reset the 'with_subselect' there. */ /*TODO: also reset the 'with_subselect' there. */
/* n. Adjust the parent_join->tables counter */ /* n. Adjust the parent_join->table_count counter */
uint table_no= parent_join->tables; uint table_no= parent_join->table_count;
/* n. Walk through child's tables and adjust table->map */ /* n. Walk through child's tables and adjust table->map */
for (tl= subq_lex->leaf_tables; tl; tl= tl->next_leaf, table_no++) for (tl= subq_lex->leaf_tables; tl; tl= tl->next_leaf, table_no++)
{ {
...@@ -1111,7 +1115,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) ...@@ -1111,7 +1115,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
emb= emb->embedding) emb= emb->embedding)
emb->select_lex= parent_join->select_lex; emb->select_lex= parent_join->select_lex;
} }
parent_join->tables += subq_lex->join->tables; parent_join->table_count += subq_lex->join->table_count;
/* /*
Put the subquery's WHERE into semi-join's sj_on_expr Put the subquery's WHERE into semi-join's sj_on_expr
...@@ -1300,11 +1304,11 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, ...@@ -1300,11 +1304,11 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
((subselect_hash_sj_engine*)subq_pred->engine); ((subselect_hash_sj_engine*)subq_pred->engine);
jtbm->table= hash_sj_engine->tmp_table; jtbm->table= hash_sj_engine->tmp_table;
jtbm->table->tablenr= parent_join->tables; jtbm->table->tablenr= parent_join->table_count;
jtbm->table->map= table_map(1) << (parent_join->tables); jtbm->table->map= table_map(1) << (parent_join->table_count);
parent_join->tables++; parent_join->table_count++;
DBUG_ASSERT(parent_join->tables < MAX_TABLES); DBUG_ASSERT(parent_join->table_count < MAX_TABLES);
Item *conds= hash_sj_engine->semi_join_conds; Item *conds= hash_sj_engine->semi_join_conds;
conds->fix_after_pullout(parent_lex, &conds); conds->fix_after_pullout(parent_lex, &conds);
...@@ -2479,7 +2483,7 @@ at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab, ...@@ -2479,7 +2483,7 @@ at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab,
void fix_semijoin_strategies_for_picked_join_order(JOIN *join) void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
{ {
uint table_count=join->tables; uint table_count=join->table_count;
uint tablenr; uint tablenr;
table_map remaining_tables= 0; table_map remaining_tables= 0;
table_map handled_tabs= 0; table_map handled_tabs= 0;
...@@ -2643,8 +2647,6 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) ...@@ -2643,8 +2647,6 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
} }
} }
enum_nested_loop_state
end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
/* /*
Setup semi-join materialization strategy for one semi-join nest Setup semi-join materialization strategy for one semi-join nest
...@@ -3505,6 +3507,7 @@ int do_sj_dups_weedout(THD *thd, SJ_TMP_TABLE *sjtbl) ...@@ -3505,6 +3507,7 @@ int do_sj_dups_weedout(THD *thd, SJ_TMP_TABLE *sjtbl)
FALSE OK FALSE OK
TRUE Out of memory error TRUE Out of memory error
*/ */
JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_const_tables const_tbls);
int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
uint no_jbuf_after) uint no_jbuf_after)
...@@ -3513,16 +3516,18 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, ...@@ -3513,16 +3516,18 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
THD *thd= join->thd; THD *thd= join->thd;
DBUG_ENTER("setup_semijoin_dups_elimination"); DBUG_ENTER("setup_semijoin_dups_elimination");
for (i= join->const_tables ; i < join->tables; ) POSITION *pos= join->best_positions + join->const_tables;
for (i= join->const_tables ; i < join->top_jtrange_tables; )
{ {
JOIN_TAB *tab=join->join_tab + i; JOIN_TAB *tab=join->join_tab + i;
POSITION *pos= join->best_positions + i; //POSITION *pos= join->best_positions + i;
uint keylen, keyno; uint keylen, keyno;
switch (pos->sj_strategy) { switch (pos->sj_strategy) {
case SJ_OPT_MATERIALIZE: case SJ_OPT_MATERIALIZE:
case SJ_OPT_MATERIALIZE_SCAN: case SJ_OPT_MATERIALIZE_SCAN:
/* Do nothing */ /* Do nothing */
i+= pos->n_sj_tables; i+= 1;// It used to be pos->n_sj_tables, but now they are embedded in a nest
pos += pos->n_sj_tables;
break; break;
case SJ_OPT_LOOSE_SCAN: case SJ_OPT_LOOSE_SCAN:
{ {
...@@ -3539,6 +3544,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, ...@@ -3539,6 +3544,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
if (pos->n_sj_tables > 1) if (pos->n_sj_tables > 1)
tab[pos->n_sj_tables - 1].do_firstmatch= tab; tab[pos->n_sj_tables - 1].do_firstmatch= tab;
i+= pos->n_sj_tables; i+= pos->n_sj_tables;
pos+= pos->n_sj_tables;
break; break;
} }
case SJ_OPT_DUPS_WEEDOUT: case SJ_OPT_DUPS_WEEDOUT:
...@@ -3636,6 +3642,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, ...@@ -3636,6 +3642,7 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
join->join_tab[i + pos->n_sj_tables - 1].check_weed_out_table= sjtbl; join->join_tab[i + pos->n_sj_tables - 1].check_weed_out_table= sjtbl;
i+= pos->n_sj_tables; i+= pos->n_sj_tables;
pos+= pos->n_sj_tables;
break; break;
} }
case SJ_OPT_FIRST_MATCH: case SJ_OPT_FIRST_MATCH:
...@@ -3658,10 +3665,12 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, ...@@ -3658,10 +3665,12 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
} }
j[-1].do_firstmatch= jump_to; j[-1].do_firstmatch= jump_to;
i+= pos->n_sj_tables; i+= pos->n_sj_tables;
pos+= pos->n_sj_tables;
break; break;
} }
case SJ_OPT_NONE: case SJ_OPT_NONE:
i++; i++;
pos++;
break; break;
} }
} }
...@@ -3848,7 +3857,7 @@ int rewrite_to_index_subquery_engine(JOIN *join) ...@@ -3848,7 +3857,7 @@ int rewrite_to_index_subquery_engine(JOIN *join)
if (!join->group_list && !join->order && if (!join->group_list && !join->order &&
join->unit->item && join->unit->item &&
join->unit->item->substype() == Item_subselect::IN_SUBS && join->unit->item->substype() == Item_subselect::IN_SUBS &&
join->tables == 1 && join->conds && join->table_count == 1 && join->conds &&
!join->unit->is_union()) !join->unit->is_union())
{ {
if (!join->having) if (!join->having)
......
...@@ -381,14 +381,14 @@ Sensitive_cursor::open(JOIN *join_arg) ...@@ -381,14 +381,14 @@ Sensitive_cursor::open(JOIN *join_arg)
/* Prepare JOIN for reading rows. */ /* Prepare JOIN for reading rows. */
join->tmp_table= 0; join->tmp_table= 0;
join->join_tab[join->tables-1].next_select= setup_end_select_func(join); join->join_tab[join->top_jtrange_tables - 1].next_select= setup_end_select_func(join);
join->send_records= 0; join->send_records= 0;
join->fetch_limit= join->unit->offset_limit_cnt; join->fetch_limit= join->unit->offset_limit_cnt;
/* Disable JOIN CACHE as it is not working with cursors yet */ /* Disable JOIN CACHE as it is not working with cursors yet */
for (JOIN_TAB *tab= join_tab; for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_CONST_TABLES);
tab != join->join_tab + join->tables - 1; tab != join->join_tab + join->top_jtrange_tables - 1;
tab++) tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
{ {
if (tab->next_select == sub_select_cache) if (tab->next_select == sub_select_cache)
tab->next_select= sub_select; tab->next_select= sub_select;
......
...@@ -677,9 +677,10 @@ multi_delete::initialize_tables(JOIN *join) ...@@ -677,9 +677,10 @@ multi_delete::initialize_tables(JOIN *join)
walk= delete_tables; walk= delete_tables;
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
tab < end; for (JOIN_TAB *tab= first_linear_tab(join, WITH_CONST_TABLES);
tab++) tab;
tab= next_linear_tab(join, tab, WITH_BUSH_ROOTS))
{ {
if (tab->table->map & tables_to_delete_from) if (tab->table->map & tables_to_delete_from)
{ {
......
This diff is collapsed.
...@@ -647,7 +647,13 @@ class JOIN :public Sql_alloc ...@@ -647,7 +647,13 @@ class JOIN :public Sql_alloc
passing 1st non-const table to filesort(). NULL means no such table exists. passing 1st non-const table to filesort(). NULL means no such table exists.
*/ */
TABLE *sort_by_table; TABLE *sort_by_table;
uint tables; /**< Number of tables in the join */ /*
Number of tables in the join.
(In MySQL, it is named 'tables' and is also the number of elements in
join->join_tab array. In MariaDB, the latter is not true, so we've renamed
the variable)
*/
uint table_count;
uint outer_tables; /**< Number of tables that are not inside semijoin */ uint outer_tables; /**< Number of tables that are not inside semijoin */
uint const_tables; uint const_tables;
/* /*
...@@ -899,7 +905,7 @@ class JOIN :public Sql_alloc ...@@ -899,7 +905,7 @@ class JOIN :public Sql_alloc
{ {
join_tab= join_tab_save= 0; join_tab= join_tab_save= 0;
table= 0; table= 0;
tables= 0; table_count= 0;
top_jtrange_tables= 0; top_jtrange_tables= 0;
const_tables= 0; const_tables= 0;
eliminated_tables= 0; eliminated_tables= 0;
...@@ -1015,7 +1021,7 @@ class JOIN :public Sql_alloc ...@@ -1015,7 +1021,7 @@ class JOIN :public Sql_alloc
} }
inline table_map all_tables_map() inline table_map all_tables_map()
{ {
return (table_map(1) << tables) - 1; return (table_map(1) << table_count) - 1;
} }
/* /*
Return the table for which an index scan can be used to satisfy Return the table for which an index scan can be used to satisfy
......
...@@ -690,7 +690,7 @@ bool st_select_lex_unit::cleanup() ...@@ -690,7 +690,7 @@ bool st_select_lex_unit::cleanup()
if ((join= fake_select_lex->join)) if ((join= fake_select_lex->join))
{ {
join->tables_list= 0; join->tables_list= 0;
join->tables= 0; join->table_count= 0;
join->top_jtrange_tables= 0; join->top_jtrange_tables= 0;
} }
error|= fake_select_lex->cleanup(); error|= fake_select_lex->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