Commit ab4a13b2 authored by Sergey Petrunya's avatar Sergey Petrunya

Switching [EXPLAIN] UPDATE/DELETE to rely on query plan footprints.

This requires that subselect's footprints are saved before it is deleted.

Attempt to save select's QPF exposes one to a variety of edge cases:
- the select may be a UNION's "fake select" which has no valid id
- optimization may fail in the middle (but subsequent JOIN::optimize() calls
  will succeed, despite the fact that there never was a query plan)
parent 52cfa54c
......@@ -4341,7 +4341,8 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
if (!first->next_select())
{
/* This is a 1-way UNION, i.e. not really a UNION */
first->save_qpf(output);
if (!output->get_select(first->select_number))
first->save_qpf(output);
return 0;
}
......@@ -4371,7 +4372,8 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
{
sl->save_qpf(output);
if (!output->get_select(sl->select_number))
sl->save_qpf(output);
qpfu->add_select(sl->select_number);
}
......
......@@ -1005,17 +1005,26 @@ err:
int JOIN::optimize()
{
bool was_optimized= optimized;
int res= optimize_inner();
/*
If we're inside a non-correlated subquery, this function may be
called for the second time after the subquery has been executed
and deleted. The second call will not produce a valid query plan, it will
short-circuit because optimized==TRUE.
"was_optimized != optimized" is here to handle this case:
- first optimization starts, gets an error (from a const. cheap
subquery), returns 1
- another JOIN::optimize() call made, and now join->optimize() will
return 0, even though we never had a query plan.
*/
if (!res && have_query_plan != QEP_DELETED)
if (was_optimized != optimized && !res && have_query_plan != QEP_DELETED)
have_query_plan= QEP_AVAILABLE;
return res;
}
/**
global select optimisation.
......@@ -2301,7 +2310,6 @@ void JOIN::exec()
select_lex->select_number))
dbug_serve_apcs(thd, 1);
);
thd->apc_target.disable();
}
......@@ -11099,7 +11107,33 @@ void JOIN::cleanup(bool full)
DBUG_PRINT("enter", ("full %u", (uint) full));
if (full)
{
//
if (select_lex->select_number != UINT_MAX &&
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
have_query_plan != QEP_NOT_PRESENT_YET &&
!thd->lex->query_plan_footprint->get_select(select_lex->select_number))
{
const char *message= NULL;
if (!table_count || !tables_list || zero_result_cause)
{
/* It's a degenerate join */
message= zero_result_cause ? zero_result_cause : "No tables used";
}
save_qpf(thd->lex->query_plan_footprint,
need_tmp, // need_tmp_table
!skip_sort_order && !no_order &&
(order || group_list), // bool need_order
select_distinct, // bool distinct
message); // message
}
//
have_query_plan= QEP_DELETED; //psergey: this is a problem!
}
if (table)
{
......
......@@ -1462,12 +1462,6 @@ public:
{
return (unit->item && unit->item->is_in_predicate());
}
/*
int print_explain(select_result_sink *result, uint8 explain_flags,
bool on_the_fly,
bool need_tmp_table, bool need_order,
bool distinct,const char *message);
*/
int save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
bool distinct, const char *message);
private:
......
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