summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc130
1 files changed, 126 insertions, 4 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 5f18d9861a9..3c183d95b42 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -503,6 +503,7 @@ void lex_start(THD *thd)
lex->expr_allows_subselect= TRUE;
lex->use_only_table_context= FALSE;
lex->parse_vcol_expr= FALSE;
+ lex->verbose= 0;
lex->name.str= 0;
lex->name.length= 0;
@@ -1889,6 +1890,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;
@@ -3480,7 +3482,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;
}
@@ -3930,9 +3932,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())
@@ -3954,6 +3959,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);
@@ -4006,10 +4014,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;
}
@@ -4156,6 +4169,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.
@@ -4174,7 +4297,6 @@ bool LEX::is_partition_management() const
alter_info.flags == ALTER_REORGANIZE_PARTITION));
}
-
#ifdef MYSQL_SERVER
uint binlog_unsafe_map[256];