mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
SHOW EXPLAIN: merge to 10.0-base.
This commit is contained in:
128
sql/sql_lex.cc
128
sql/sql_lex.cc
@ -1883,6 +1883,7 @@ void st_select_lex::init_query()
|
||||
nest_level= 0;
|
||||
link_next= 0;
|
||||
is_prep_leaf_list_saved= FALSE;
|
||||
have_merged_subqueries= FALSE;
|
||||
bzero((char*) expr_cache_may_be_used, sizeof(expr_cache_may_be_used));
|
||||
m_non_agg_field_used= false;
|
||||
m_agg_func_used= false;
|
||||
@ -3474,7 +3475,7 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
|
||||
if (options & SELECT_DESCRIBE)
|
||||
{
|
||||
/* Optimize the subquery in the context of EXPLAIN. */
|
||||
sl->set_explain_type();
|
||||
sl->set_explain_type(FALSE);
|
||||
sl->options|= SELECT_DESCRIBE;
|
||||
inner_join->select_options|= SELECT_DESCRIBE;
|
||||
}
|
||||
@ -3924,9 +3925,12 @@ void st_select_lex::update_correlated_cache()
|
||||
|
||||
/**
|
||||
Set the EXPLAIN type for this subquery.
|
||||
|
||||
@param on_the_fly TRUE<=> We're running a SHOW EXPLAIN command, so we must
|
||||
not change any variables
|
||||
*/
|
||||
|
||||
void st_select_lex::set_explain_type()
|
||||
void st_select_lex::set_explain_type(bool on_the_fly)
|
||||
{
|
||||
bool is_primary= FALSE;
|
||||
if (next_select())
|
||||
@ -3948,6 +3952,9 @@ void st_select_lex::set_explain_type()
|
||||
}
|
||||
}
|
||||
|
||||
if (on_the_fly && !is_primary && have_merged_subqueries)
|
||||
is_primary= TRUE;
|
||||
|
||||
SELECT_LEX *first= master_unit()->first_select();
|
||||
/* drop UNCACHEABLE_EXPLAIN, because it is for internal usage only */
|
||||
uint8 is_uncacheable= (uncacheable & ~UNCACHEABLE_EXPLAIN);
|
||||
@ -4000,10 +4007,15 @@ void st_select_lex::set_explain_type()
|
||||
else
|
||||
{
|
||||
type= is_uncacheable ? "UNCACHEABLE UNION": "UNION";
|
||||
if (this == master_unit()->fake_select_lex)
|
||||
type= "UNION RESULT";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
options|= SELECT_DESCRIBE;
|
||||
|
||||
if (!on_the_fly)
|
||||
options|= SELECT_DESCRIBE;
|
||||
}
|
||||
|
||||
|
||||
@ -4150,6 +4162,116 @@ bool st_select_lex::is_merged_child_of(st_select_lex *ancestor)
|
||||
}
|
||||
|
||||
|
||||
int print_explain_message_line(select_result_sink *result,
|
||||
SELECT_LEX *select_lex,
|
||||
bool on_the_fly,
|
||||
uint8 options,
|
||||
const char *message);
|
||||
|
||||
|
||||
int st_select_lex::print_explain(select_result_sink *output,
|
||||
uint8 explain_flags,
|
||||
bool *printed_anything)
|
||||
{
|
||||
int res;
|
||||
if (join && join->have_query_plan == JOIN::QEP_AVAILABLE)
|
||||
{
|
||||
/*
|
||||
There is a number of reasons join can be marked as degenerate, so all
|
||||
three conditions below can happen simultaneously, or individually:
|
||||
*/
|
||||
*printed_anything= TRUE;
|
||||
if (!join->table_count || !join->tables_list || join->zero_result_cause)
|
||||
{
|
||||
/* It's a degenerate join */
|
||||
const char *cause= join->zero_result_cause ? join-> zero_result_cause :
|
||||
"No tables used";
|
||||
res= join->print_explain(output, explain_flags, TRUE, FALSE, FALSE,
|
||||
FALSE, cause);
|
||||
}
|
||||
else
|
||||
{
|
||||
res= join->print_explain(output, explain_flags, TRUE,
|
||||
join->need_tmp, // need_tmp_table
|
||||
!join->skip_sort_order && !join->no_order &&
|
||||
(join->order || join->group_list), // bool need_order
|
||||
join->select_distinct, // bool distinct
|
||||
NULL); //const char *message
|
||||
}
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
|
||||
unit;
|
||||
unit= unit->next_unit())
|
||||
{
|
||||
/*
|
||||
Display subqueries only if they are not parts of eliminated WHERE/ON
|
||||
clauses.
|
||||
*/
|
||||
if (!(unit->item && unit->item->eliminated))
|
||||
{
|
||||
if ((res= unit->print_explain(output, explain_flags, printed_anything)))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *msg;
|
||||
if (!join)
|
||||
DBUG_ASSERT(0); /* Seems not to be possible */
|
||||
|
||||
/* Not printing anything useful, don't touch *printed_anything here */
|
||||
if (join->have_query_plan == JOIN::QEP_NOT_PRESENT_YET)
|
||||
msg= "Not yet optimized";
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(join->have_query_plan == JOIN::QEP_DELETED);
|
||||
msg= "Query plan already deleted";
|
||||
}
|
||||
res= print_explain_message_line(output, this, TRUE /* on_the_fly */,
|
||||
0, msg);
|
||||
}
|
||||
err:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int st_select_lex_unit::print_explain(select_result_sink *output,
|
||||
uint8 explain_flags, bool *printed_anything)
|
||||
{
|
||||
int res= 0;
|
||||
SELECT_LEX *first= first_select();
|
||||
|
||||
if (first && !first->next_select() && !first->join)
|
||||
{
|
||||
/*
|
||||
If there is only one child, 'first', and it has join==NULL, emit "not in
|
||||
EXPLAIN state" error.
|
||||
*/
|
||||
const char *msg="Query plan already deleted";
|
||||
res= print_explain_message_line(output, first, TRUE /* on_the_fly */,
|
||||
0, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
|
||||
{
|
||||
if ((res= sl->print_explain(output, explain_flags, printed_anything)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Note: fake_select_lex->join may be NULL or non-NULL at this point */
|
||||
if (fake_select_lex)
|
||||
{
|
||||
res= print_fake_select_lex_join(output, TRUE /* on the fly */,
|
||||
fake_select_lex, explain_flags);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A routine used by the parser to decide whether we are specifying a full
|
||||
partitioning or if only partitions to add or to split.
|
||||
|
Reference in New Issue
Block a user