Commit 5de770f3 authored by Sergey Petrunya's avatar Sergey Petrunya

MWL#90: Address review feedback part #14

parent 290a72d5
...@@ -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)
...@@ -3512,17 +3515,19 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options, ...@@ -3512,17 +3515,19 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
uint i; uint i;
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)
{ {
......
...@@ -520,7 +520,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -520,7 +520,7 @@ JOIN::prepare(Item ***rref_pointer_array,
for (table_ptr= select_lex->leaf_tables; for (table_ptr= select_lex->leaf_tables;
table_ptr; table_ptr;
table_ptr= table_ptr->next_leaf) table_ptr= table_ptr->next_leaf)
tables++; table_count++;
if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) || select_lex->setup_ref_array(thd, og_num) ||
...@@ -840,7 +840,7 @@ JOIN::optimize() ...@@ -840,7 +840,7 @@ JOIN::optimize()
"Impossible HAVING" : "Impossible WHERE")); "Impossible HAVING" : "Impossible WHERE"));
zero_result_cause= having_value == Item::COND_FALSE ? zero_result_cause= having_value == Item::COND_FALSE ?
"Impossible HAVING" : "Impossible WHERE"; "Impossible HAVING" : "Impossible WHERE";
tables= 0; table_count= 0;
error= 0; error= 0;
goto setup_subq_exit; goto setup_subq_exit;
} }
...@@ -890,7 +890,7 @@ JOIN::optimize() ...@@ -890,7 +890,7 @@ JOIN::optimize()
{ {
DBUG_PRINT("info",("No matching min/max row")); DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row"; zero_result_cause= "No matching min/max row";
tables= 0; table_count= 0;
error=0; error=0;
goto setup_subq_exit; goto setup_subq_exit;
} }
...@@ -904,14 +904,14 @@ JOIN::optimize() ...@@ -904,14 +904,14 @@ JOIN::optimize()
{ {
DBUG_PRINT("info",("No matching min/max row")); DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row"; zero_result_cause= "No matching min/max row";
tables= 0; table_count= 0;
error=0; error=0;
goto setup_subq_exit; goto setup_subq_exit;
} }
DBUG_PRINT("info",("Select tables optimized away")); DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away"; zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved tables_list= 0; // All tables resolved
const_tables= tables; const_tables= table_count;
/* /*
Extract all table-independent conditions and replace the WHERE Extract all table-independent conditions and replace the WHERE
clause with them. All other conditions were computed by opt_sum_query clause with them. All other conditions were computed by opt_sum_query
...@@ -967,7 +967,7 @@ JOIN::optimize() ...@@ -967,7 +967,7 @@ JOIN::optimize()
else else
{ {
/* Remove distinct if only const tables */ /* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables); select_distinct= select_distinct && (const_tables != table_count);
} }
thd_proc_info(thd, "preparing"); thd_proc_info(thd, "preparing");
...@@ -1125,7 +1125,7 @@ JOIN::optimize() ...@@ -1125,7 +1125,7 @@ JOIN::optimize()
The FROM clause must contain a single non-constant table. The FROM clause must contain a single non-constant table.
*/ */
if (tables - const_tables == 1 && (group_list || select_distinct) && if (table_count - const_tables == 1 && (group_list || select_distinct) &&
!tmp_table_param.sum_func_count && !tmp_table_param.sum_func_count &&
(!join_tab[const_tables].select || (!join_tab[const_tables].select ||
!join_tab[const_tables].select->quick || !join_tab[const_tables].select->quick ||
...@@ -1176,7 +1176,7 @@ JOIN::optimize() ...@@ -1176,7 +1176,7 @@ JOIN::optimize()
if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE) if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE)
select_distinct=0; select_distinct=0;
} }
else if (select_distinct && tables - const_tables == 1 && else if (select_distinct && table_count - const_tables == 1 &&
rollup.state == ROLLUP::STATE_NONE) rollup.state == ROLLUP::STATE_NONE)
{ {
/* /*
...@@ -1305,7 +1305,7 @@ JOIN::optimize() ...@@ -1305,7 +1305,7 @@ JOIN::optimize()
When the WITH ROLLUP modifier is present, we cannot skip temporary table When the WITH ROLLUP modifier is present, we cannot skip temporary table
creation for the DISTINCT clause just because there are only const tables. creation for the DISTINCT clause just because there are only const tables.
*/ */
need_tmp= ((const_tables != tables && need_tmp= ((const_tables != table_count &&
((select_distinct || !simple_order || !simple_group) || ((select_distinct || !simple_order || !simple_group) ||
(group_list && order) || (group_list && order) ||
test(select_options & OPTION_BUFFER_RESULT))) || test(select_options & OPTION_BUFFER_RESULT))) ||
...@@ -1319,7 +1319,7 @@ JOIN::optimize() ...@@ -1319,7 +1319,7 @@ JOIN::optimize()
Yet the current implementation of FORCE INDEX hints does not Yet the current implementation of FORCE INDEX hints does not
allow us to do it in a clean manner. allow us to do it in a clean manner.
*/ */
no_jbuf_after= 1 ? tables : make_join_orderinfo(this); no_jbuf_after= 1 ? table_count : make_join_orderinfo(this);
select_opts_for_readinfo= select_opts_for_readinfo=
(select_options & (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) | (select_options & (SELECT_DESCRIBE | SELECT_NO_JOIN_CACHE)) |
...@@ -1351,7 +1351,7 @@ JOIN::optimize() ...@@ -1351,7 +1351,7 @@ JOIN::optimize()
*/ */
if (need_tmp || select_distinct || group_list || order) if (need_tmp || select_distinct || group_list || order)
{ {
for (uint i= 0; i < tables; i++) for (uint i= 0; i < table_count; i++)
{ {
if (!(table[i]->map & const_table_map)) if (!(table[i]->map & const_table_map))
table[i]->prepare_for_position(); table[i]->prepare_for_position();
...@@ -1360,7 +1360,7 @@ JOIN::optimize() ...@@ -1360,7 +1360,7 @@ JOIN::optimize()
DBUG_EXECUTE("info",TEST_join(this);); DBUG_EXECUTE("info",TEST_join(this););
if (const_tables != tables) if (const_tables != table_count)
{ {
/* /*
Because filesort always does a full table scan or a quick range scan Because filesort always does a full table scan or a quick range scan
...@@ -1535,7 +1535,7 @@ JOIN::optimize() ...@@ -1535,7 +1535,7 @@ JOIN::optimize()
if (exec_tmp_table1->distinct) if (exec_tmp_table1->distinct)
{ {
table_map used_tables= thd->used_tables; table_map used_tables= thd->used_tables;
JOIN_TAB *last_join_tab= join_tab+tables-1; JOIN_TAB *last_join_tab= join_tab + top_jtrange_tables - 1;
do do
{ {
if (used_tables & last_join_tab->table->map) if (used_tables & last_join_tab->table->map)
...@@ -1761,12 +1761,17 @@ JOIN::reinit() ...@@ -1761,12 +1761,17 @@ JOIN::reinit()
set_items_ref_array(items0); set_items_ref_array(items0);
if (join_tab_save) if (join_tab_save)
memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * table_count);
/* need to reset ref access state (see join_read_key) */ /* need to reset ref access state (see join_read_key) */
if (join_tab) if (join_tab)
for (uint i= 0; i < tables; i++) {
join_tab[i].ref.key_err= TRUE; for (JOIN_TAB *tab= first_linear_tab(this, WITH_CONST_TABLES); tab;
tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
{
tab->ref.key_err= TRUE;
}
}
if (tmp_join) if (tmp_join)
restore_tmp(); restore_tmp();
...@@ -1823,7 +1828,7 @@ JOIN::save_join_tab() ...@@ -1823,7 +1828,7 @@ JOIN::save_join_tab()
if (!join_tab_save && select_lex->master_unit()->uncacheable) if (!join_tab_save && select_lex->master_unit()->uncacheable)
{ {
if (!(join_tab_save= (JOIN_TAB*)thd->memdup((uchar*) join_tab, if (!(join_tab_save= (JOIN_TAB*)thd->memdup((uchar*) join_tab,
sizeof(JOIN_TAB) * tables))) sizeof(JOIN_TAB) * table_count)))
return 1; return 1;
} }
return 0; return 0;
...@@ -1863,7 +1868,7 @@ JOIN::exec() ...@@ -1863,7 +1868,7 @@ JOIN::exec()
} }
(void) result->prepare2(); // Currently, this cannot fail. (void) result->prepare2(); // Currently, this cannot fail.
if (!tables_list && (tables || !select_lex->with_sum_func)) if (!tables_list && (table_count || !select_lex->with_sum_func))
{ // Only test of functions { // Only test of functions
if (select_options & SELECT_DESCRIBE) if (select_options & SELECT_DESCRIBE)
select_describe(this, FALSE, FALSE, FALSE, select_describe(this, FALSE, FALSE, FALSE,
...@@ -1916,7 +1921,7 @@ JOIN::exec() ...@@ -1916,7 +1921,7 @@ JOIN::exec()
FOUND_ROWS() may be called. Never reset the examined row count here. FOUND_ROWS() may be called. Never reset the examined row count here.
It must be accumulated from all join iterations of all join parts. It must be accumulated from all join iterations of all join parts.
*/ */
if (tables) if (table_count)
thd->limit_found_rows= 0; thd->limit_found_rows= 0;
if (zero_result_cause) if (zero_result_cause)
...@@ -1953,7 +1958,7 @@ JOIN::exec() ...@@ -1953,7 +1958,7 @@ JOIN::exec()
} }
if (order && if (order &&
(order != group_list || !(select_options & SELECT_BIG_RESULT)) && (order != group_list || !(select_options & SELECT_BIG_RESULT)) &&
(const_tables == tables || (const_tables == table_count ||
((simple_order || skip_sort_order) && ((simple_order || skip_sort_order) &&
test_if_skip_sort_order(&join_tab[const_tables], order, test_if_skip_sort_order(&join_tab[const_tables], order,
select_limit, 0, select_limit, 0,
...@@ -1964,7 +1969,7 @@ JOIN::exec() ...@@ -1964,7 +1969,7 @@ JOIN::exec()
select_describe(this, need_tmp, select_describe(this, need_tmp,
order != 0 && !skip_sort_order, order != 0 && !skip_sort_order,
select_distinct, select_distinct,
!tables ? "No tables used" : NullS); !table_count ? "No tables used" : NullS);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -1998,7 +2003,7 @@ JOIN::exec() ...@@ -1998,7 +2003,7 @@ JOIN::exec()
thd_proc_info(thd, copy_to_tmp_table); thd_proc_info(thd, copy_to_tmp_table);
DBUG_PRINT("info", ("%s", thd->proc_info)); DBUG_PRINT("info", ("%s", thd->proc_info));
if (!curr_join->sort_and_group && if (!curr_join->sort_and_group &&
curr_join->const_tables != curr_join->tables) curr_join->const_tables != curr_join->table_count)
{ {
JOIN_TAB *first_tab= curr_join->join_tab + curr_join->const_tables; JOIN_TAB *first_tab= curr_join->join_tab + curr_join->const_tables;
first_tab->sorted= test(first_tab->loosescan_match_tab); first_tab->sorted= test(first_tab->loosescan_match_tab);
...@@ -2169,7 +2174,7 @@ JOIN::exec() ...@@ -2169,7 +2174,7 @@ JOIN::exec()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
curr_join->group_list= 0; curr_join->group_list= 0;
if (!curr_join->sort_and_group && if (!curr_join->sort_and_group &&
curr_join->const_tables != curr_join->tables) curr_join->const_tables != curr_join->table_count)
{ {
JOIN_TAB *first_tab= curr_join->join_tab + curr_join->const_tables; JOIN_TAB *first_tab= curr_join->join_tab + curr_join->const_tables;
first_tab->sorted= test(first_tab->loosescan_match_tab); first_tab->sorted= test(first_tab->loosescan_match_tab);
...@@ -2182,7 +2187,7 @@ JOIN::exec() ...@@ -2182,7 +2187,7 @@ JOIN::exec()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
end_read_record(&curr_join->join_tab->read_record); end_read_record(&curr_join->join_tab->read_record);
curr_join->const_tables= curr_join->tables; // Mark free for cleanup() curr_join->const_tables= curr_join->table_count; // Mark free for cleanup()
curr_join->join_tab[0].table= 0; // Table is freed curr_join->join_tab[0].table= 0; // Table is freed
// No sum funcs anymore // No sum funcs anymore
...@@ -2385,7 +2390,7 @@ JOIN::exec() ...@@ -2385,7 +2390,7 @@ JOIN::exec()
curr_join->group_list ? TRUE : FALSE)) curr_join->group_list ? TRUE : FALSE))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
sortorder= curr_join->sortorder; sortorder= curr_join->sortorder;
if (curr_join->const_tables != curr_join->tables && if (curr_join->const_tables != curr_join->table_count &&
!curr_join->join_tab[curr_join->const_tables].table->sort.io_cache) !curr_join->join_tab[curr_join->const_tables].table->sort.io_cache)
{ {
/* /*
...@@ -2407,7 +2412,7 @@ JOIN::exec() ...@@ -2407,7 +2412,7 @@ JOIN::exec()
curr_join->fields= curr_fields_list; curr_join->fields= curr_fields_list;
curr_join->procedure= procedure; curr_join->procedure= procedure;
if (is_top_level_join() && thd->cursor && tables != const_tables) if (is_top_level_join() && thd->cursor && table_count != const_tables)
{ {
/* /*
We are here if this is JOIN::exec for the last select of the main unit We are here if this is JOIN::exec for the last select of the main unit
...@@ -2474,9 +2479,11 @@ JOIN::destroy() ...@@ -2474,9 +2479,11 @@ JOIN::destroy()
{ {
if (join_tab != tmp_join->join_tab) if (join_tab != tmp_join->join_tab)
{ {
JOIN_TAB *tab, *end; for (JOIN_TAB *tab= first_linear_tab(this, WITH_CONST_TABLES); tab;
for (tab= join_tab, end= tab+tables ; tab != end ; tab++) tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
{
tab->cleanup(); tab->cleanup();
}
} }
tmp_join->tmp_join= 0; tmp_join->tmp_join= 0;
/* /*
...@@ -2801,7 +2808,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -2801,7 +2808,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
DBUG_ENTER("make_join_statistics"); DBUG_ENTER("make_join_statistics");
LINT_INIT(table); /* inited in all loops */ LINT_INIT(table); /* inited in all loops */
table_count=join->tables; table_count=join->table_count;
stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*(table_count)); stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*(table_count));
stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES); stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
...@@ -2943,7 +2950,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -2943,7 +2950,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
{ {
if (s->dependent & s->table->map) if (s->dependent & s->table->map)
{ {
join->tables=0; // Don't use join->table join->table_count=0; // Don't use join->table
my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0)); my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
goto error; goto error;
} }
...@@ -2952,7 +2959,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -2952,7 +2959,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
} }
if (conds || outer_join) if (conds || outer_join)
if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables, if (update_ref_and_keys(join->thd, keyuse_array, stat, join->table_count,
conds, join->cond_equal, conds, join->cond_equal,
~outer_join, join->select_lex, &sargables)) ~outer_join, join->select_lex, &sargables))
goto error; goto error;
...@@ -3269,14 +3276,14 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -3269,14 +3276,14 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
join->const_tables=const_count; join->const_tables=const_count;
join->found_const_table_map=found_const_table_map; join->found_const_table_map=found_const_table_map;
if (join->const_tables != join->tables) if (join->const_tables != join->table_count)
optimize_keyuse(join, keyuse_array); optimize_keyuse(join, keyuse_array);
if (optimize_semijoin_nests(join, all_table_map)) if (optimize_semijoin_nests(join, all_table_map))
DBUG_RETURN(TRUE); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */
/* Find an optimal join order of the non-constant tables. */ /* Find an optimal join order of the non-constant tables. */
if (join->const_tables != join->tables) if (join->const_tables != join->table_count)
{ {
if (choose_plan(join, all_table_map & ~join->const_table_map)) if (choose_plan(join, all_table_map & ~join->const_table_map))
goto error; goto error;
...@@ -5299,7 +5306,7 @@ choose_plan(JOIN *join, table_map join_tables) ...@@ -5299,7 +5306,7 @@ choose_plan(JOIN *join, table_map join_tables)
jtab_sort_func= straight_join ? join_tab_cmp_straight : join_tab_cmp; jtab_sort_func= straight_join ? join_tab_cmp_straight : join_tab_cmp;
} }
my_qsort2(join->best_ref + join->const_tables, my_qsort2(join->best_ref + join->const_tables,
join->tables - join->const_tables, sizeof(JOIN_TAB*), join->table_count - join->const_tables, sizeof(JOIN_TAB*),
jtab_sort_func, (void*)join->emb_sjm_nest); jtab_sort_func, (void*)join->emb_sjm_nest);
join->cur_sj_inner_tables= 0; join->cur_sj_inner_tables= 0;
...@@ -5475,7 +5482,7 @@ join_tab_cmp_embedded_first(const void *emb, const void* ptr1, const void* ptr2 ...@@ -5475,7 +5482,7 @@ join_tab_cmp_embedded_first(const void *emb, const void* ptr1, const void* ptr2
static uint static uint
determine_search_depth(JOIN *join) determine_search_depth(JOIN *join)
{ {
uint table_count= join->tables - join->const_tables; uint table_count= join->table_count - join->const_tables;
uint search_depth; uint search_depth;
/* TODO: this value should be determined dynamically, based on statistics: */ /* TODO: this value should be determined dynamically, based on statistics: */
uint max_tables_for_exhaustive_opt= 7; uint max_tables_for_exhaustive_opt= 7;
...@@ -6415,6 +6422,28 @@ JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab) ...@@ -6415,6 +6422,28 @@ JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab)
} }
JOIN_TAB *first_top_level_tab(JOIN *join, enum enum_with_const_tables with_const)
{
JOIN_TAB *tab= join->join_tab;
if (with_const == WITH_CONST_TABLES)
{
if (join->const_tables == join->table_count)
return NULL;
tab += join->const_tables;
}
return tab;
}
JOIN_TAB *next_top_level_tab(JOIN *join, JOIN_TAB *tab)
{
tab= next_breadth_first_tab(join, tab);
if (tab->bush_root_tab)
tab= NULL;
return tab;
}
JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_const_tables const_tbls) JOIN_TAB *first_linear_tab(JOIN *join, enum enum_with_const_tables const_tbls)
{ {
JOIN_TAB *first= join->join_tab; JOIN_TAB *first= join->join_tab;
...@@ -6580,7 +6609,7 @@ get_best_combination(JOIN *join) ...@@ -6580,7 +6609,7 @@ get_best_combination(JOIN *join)
THD *thd=join->thd; THD *thd=join->thd;
DBUG_ENTER("get_best_combination"); DBUG_ENTER("get_best_combination");
table_count=join->tables; table_count=join->table_count;
if (!(join->join_tab=join_tab= if (!(join->join_tab=join_tab=
(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count))) (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -6629,7 +6658,6 @@ get_best_combination(JOIN *join) ...@@ -6629,7 +6658,6 @@ get_best_combination(JOIN *join)
j->on_expr_ref= (Item**) &null_ptr; j->on_expr_ref= (Item**) &null_ptr;
j->keys= key_map(1); /* The unique index is always in 'possible keys' in EXPLAIN */ j->keys= key_map(1); /* The unique index is always in 'possible keys' in EXPLAIN */
/* /*
2. Proceed with processing SJM nest's join tabs, putting them into the 2. Proceed with processing SJM nest's join tabs, putting them into the
sub-order sub-order
...@@ -7041,7 +7069,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table) ...@@ -7041,7 +7069,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
join_tab= parent->join_tab_reexec; join_tab= parent->join_tab_reexec;
table= &parent->table_reexec[0]; parent->table_reexec[0]= temp_table; table= &parent->table_reexec[0]; parent->table_reexec[0]= temp_table;
tables= top_jtrange_tables= 1; table_count= top_jtrange_tables= 1;
const_tables= 0; const_tables= 0;
const_table_map= 0; const_table_map= 0;
...@@ -7383,9 +7411,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -7383,9 +7411,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/ */
if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */ if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */
{ /* there may be a select without a cond. */ { /* there may be a select without a cond. */
if (join->tables > 1) if (join->table_count > 1)
cond->update_used_tables(); // Tablenr may have changed cond->update_used_tables(); // Tablenr may have changed
if (join->const_tables == join->tables && if (join->const_tables == join->table_count &&
thd->lex->current_select->master_unit() == thd->lex->current_select->master_unit() ==
&thd->lex->unit) // not upper level SELECT &thd->lex->unit) // not upper level SELECT
join->const_table_map|=RAND_TABLE_BIT; join->const_table_map|=RAND_TABLE_BIT;
...@@ -7486,7 +7514,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -7486,7 +7514,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
Following force including random expression in last table condition. Following force including random expression in last table condition.
It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5 It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
*/ */
if (i == join->tables-1) if (tab == join->join_tab + join->top_jtrange_tables - 1)
current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT; current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
used_tables|=current_map; used_tables|=current_map;
...@@ -7506,7 +7534,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -7506,7 +7534,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
We will use join cache here : prevent sorting of the first We will use join cache here : prevent sorting of the first
table only and sort at the end. table only and sort at the end.
*/ */
if (i != join->const_tables && join->tables > join->const_tables + 1) if (i != join->const_tables && join->table_count > join->const_tables + 1)
join->full_join= 1; join->full_join= 1;
} }
...@@ -7884,9 +7912,9 @@ static uint make_join_orderinfo(JOIN *join) ...@@ -7884,9 +7912,9 @@ static uint make_join_orderinfo(JOIN *join)
JOIN_TAB *tab; JOIN_TAB *tab;
if (join->need_tmp) if (join->need_tmp)
return join->tables; return join->table_count;
tab= join->get_sort_by_join_tab(); tab= join->get_sort_by_join_tab();
return tab ? tab-join->join_tab : join->tables; return tab ? tab-join->join_tab : join->table_count;
} }
/* /*
...@@ -8840,9 +8868,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) ...@@ -8840,9 +8868,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
bool error_if_full_join(JOIN *join) bool error_if_full_join(JOIN *join)
{ {
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables; for (JOIN_TAB *tab=first_top_level_tab(join, WITH_CONST_TABLES); tab;
tab < end; tab= next_top_level_tab(join, tab))
tab++)
{ {
if (tab->type == JT_ALL && (!tab->select || !tab->select->quick)) if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
{ {
...@@ -9085,7 +9112,7 @@ void JOIN::cleanup(bool full) ...@@ -9085,7 +9112,7 @@ void JOIN::cleanup(bool full)
Only a sorted table may be cached. This sorted table is always the Only a sorted table may be cached. This sorted table is always the
first non const table in join->table first non const table in join->table
*/ */
if (tables > const_tables) // Test for not-const tables if (table_count > const_tables) // Test for not-const tables
{ {
free_io_cache(table[const_tables]); free_io_cache(table[const_tables]);
filesort_free_buffers(table[const_tables],full); filesort_free_buffers(table[const_tables],full);
...@@ -9318,7 +9345,7 @@ static ORDER * ...@@ -9318,7 +9345,7 @@ static ORDER *
remove_const(JOIN *join,ORDER *first_order, COND *cond, remove_const(JOIN *join,ORDER *first_order, COND *cond,
bool change_list, bool *simple_order) bool change_list, bool *simple_order)
{ {
if (join->tables == join->const_tables) if (join->table_count == join->const_tables)
return change_list ? 0 : first_order; // No need to sort return change_list ? 0 : first_order; // No need to sort
ORDER *order,**prev_ptr; ORDER *order,**prev_ptr;
...@@ -9356,7 +9383,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, ...@@ -9356,7 +9383,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
table for all queries containing more than one table, ROLLUP, and an table for all queries containing more than one table, ROLLUP, and an
outer join. outer join.
*/ */
(join->tables > 1 && join->rollup.state == ROLLUP::STATE_INITED && (join->table_count > 1 && join->rollup.state == ROLLUP::STATE_INITED &&
join->outer_join)) join->outer_join))
*simple_order=0; // Must do a temp table to sort *simple_order=0; // Must do a temp table to sort
else if (!(order_tables & not_const_tables)) else if (!(order_tables & not_const_tables))
...@@ -9455,7 +9482,7 @@ static void clear_tables(JOIN *join) ...@@ -9455,7 +9482,7 @@ static void clear_tables(JOIN *join)
must clear only the non-const tables, as const tables must clear only the non-const tables, as const tables
are not re-calculated. are not re-calculated.
*/ */
for (uint i= 0 ; i < join->tables ; i++) for (uint i= 0 ; i < join->table_count ; i++)
{ {
if (!(join->table[i]->map & join->const_table_map)) if (!(join->table[i]->map & join->const_table_map))
mark_as_null_row(join->table[i]); // All fields are NULL mark_as_null_row(join->table[i]); // All fields are NULL
...@@ -13787,13 +13814,13 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -13787,13 +13814,13 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
} }
/* Set up select_end */ /* Set up select_end */
Next_select_func end_select= setup_end_select_func(join); Next_select_func end_select= setup_end_select_func(join);
if (join->tables) if (join->table_count)
{ {
join->join_tab[join->top_jtrange_tables - 1].next_select= end_select; join->join_tab[join->top_jtrange_tables - 1].next_select= end_select;
join_tab=join->join_tab+join->const_tables; join_tab=join->join_tab+join->const_tables;
} }
join->send_records=0; join->send_records=0;
if (join->tables == join->const_tables) if (join->table_count == join->const_tables)
{ {
/* /*
HAVING will be checked after processing aggregate functions, HAVING will be checked after processing aggregate functions,
...@@ -13826,7 +13853,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -13826,7 +13853,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
} }
else else
{ {
DBUG_ASSERT(join->tables); DBUG_ASSERT(join->table_count);
error= sub_select(join,join_tab,0); error= sub_select(join,join_tab,0);
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS) if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
error= sub_select(join,join_tab,1); error= sub_select(join,join_tab,1);
...@@ -14120,7 +14147,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) ...@@ -14120,7 +14147,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if (join->resume_nested_loop) if (join->resume_nested_loop)
{ {
/* If not the last table, plunge down the nested loop */ /* If not the last table, plunge down the nested loop */
if (join_tab < join->join_tab + join->tables - 1) if (join_tab < join->join_tab + join->top_jtrange_tables - 1)
rc= (*join_tab->next_select)(join, join_tab + 1, 0); rc= (*join_tab->next_select)(join, join_tab + 1, 0);
else else
{ {
...@@ -15152,7 +15179,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -15152,7 +15179,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (join->select_options & OPTION_FOUND_ROWS) if (join->select_options & OPTION_FOUND_ROWS)
{ {
JOIN_TAB *jt=join->join_tab; JOIN_TAB *jt=join->join_tab;
if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group if ((join->table_count == 1) && !join->tmp_table && !join->sort_and_group
&& !join->send_group_parts && !join->having && !jt->select_cond && && !join->send_group_parts && !join->having && !jt->select_cond &&
!(jt->select && jt->select->quick) && !(jt->select && jt->select->quick) &&
(jt->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) && (jt->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
...@@ -15460,7 +15487,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -15460,7 +15487,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
table->file->print_error(error, MYF(0));/* purecov: inspected */ table->file->print_error(error, MYF(0));/* purecov: inspected */
DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */ DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
} }
join->join_tab[join->tables-1].next_select=end_unique_update; join->join_tab[join->top_jtrange_tables-1].next_select=end_unique_update;
} }
join->send_records++; join->send_records++;
DBUG_RETURN(NESTED_LOOP_OK); DBUG_RETURN(NESTED_LOOP_OK);
...@@ -16543,7 +16570,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -16543,7 +16570,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
ref_key_quick_rows= table->quick_rows[ref_key]; ref_key_quick_rows= table->quick_rows[ref_key];
read_time= join->best_positions[tablenr].read_time; read_time= join->best_positions[tablenr].read_time;
for (uint i= tablenr+1; i < join->tables; i++) for (uint i= tablenr+1; i < join->table_count; i++)
fanout*= join->best_positions[i].records_read; // fanout is always >= 1 fanout*= join->best_positions[i].records_read; // fanout is always >= 1
for (nr=0; nr < table->s->keys ; nr++) for (nr=0; nr < table->s->keys ; nr++)
...@@ -16719,7 +16746,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ...@@ -16719,7 +16746,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/ */
if ((select_limit >= table_records) && if ((select_limit >= table_records) &&
(tab->type == JT_ALL && (tab->type == JT_ALL &&
tab->join->tables > tab->join->const_tables + 1) && tab->join->table_count > tab->join->const_tables + 1) &&
((unsigned) best_key != table->s->primary_key || ((unsigned) best_key != table->s->primary_key ||
!table->file->primary_key_is_clustered())) !table->file->primary_key_is_clustered()))
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -16919,7 +16946,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, ...@@ -16919,7 +16946,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
JOIN_TAB *tab; JOIN_TAB *tab;
DBUG_ENTER("create_sort_index"); DBUG_ENTER("create_sort_index");
if (join->tables == join->const_tables) if (join->table_count == join->const_tables)
DBUG_RETURN(0); // One row, no need to sort DBUG_RETURN(0); // One row, no need to sort
tab= join->join_tab + join->const_tables; tab= join->join_tab + join->const_tables;
table= tab->table; table= tab->table;
......
...@@ -647,7 +647,13 @@ public: ...@@ -647,7 +647,13 @@ public:
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 @@ public: ...@@ -899,7 +905,7 @@ public:
{ {
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 @@ public: ...@@ -1015,7 +1021,7 @@ public:
} }
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