summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2013-06-27 18:28:14 +0400
committerSergey Petrunya <psergey@askmonty.org>2013-06-27 18:28:14 +0400
commitef47cc1f091f76740212e125fe91f113028cbaa8 (patch)
treeda246c3fb17d79c00d4491406edffbbd373b9fbb /sql/sql_lex.cc
parent639baee61bdfefe124414db6b12d40061a086e5b (diff)
parentbefacafd73d4892f2ad84991ad7c2d4626e45c47 (diff)
downloadmariadb-git-ef47cc1f091f76740212e125fe91f113028cbaa8.tar.gz
[SHOW] EXPLAIN UPDATE/DELETE, code re-structuring
- Merge with 10.0-base
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc161
1 files changed, 81 insertions, 80 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1114723079d..8361712eed9 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -447,6 +447,8 @@ void lex_start(THD *thd)
DBUG_ENTER("lex_start");
lex->thd= lex->unit.thd= thd;
+
+ lex->query_plan_footprint= NULL;
lex->context_stack.empty();
lex->unit.init_query();
@@ -2551,7 +2553,8 @@ void Query_tables_list::destroy_query_tables_list()
*/
LEX::LEX()
- :result(0), option_type(OPT_DEFAULT), is_lex_started(0),
+ : query_plan_footprint(NULL),
+ result(0), option_type(OPT_DEFAULT), is_lex_started(0),
limit_rows_examined_cnt(ULONGLONG_MAX)
{
@@ -3493,6 +3496,18 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
is_correlated_unit|= sl->is_correlated;
inner_join->select_options= save_options;
un->thd->lex->current_select= save_select;
+ /// psergey:
+ QPF_query *qpf;
+ if ((qpf= inner_join->thd->lex->query_plan_footprint))
+ {
+ QPF_select *qp_sel;
+ if ((qp_sel= qpf->get_select(inner_join->select_lex->select_number)))
+ {
+ sl->set_explain_type(TRUE);
+ qp_sel->select_type= sl->type;
+ }
+ }
+ ///
if (empty_union_result)
{
/*
@@ -4171,89 +4186,55 @@ bool st_select_lex::is_merged_child_of(st_select_lex *ancestor)
return all_merged;
}
+/*
+ This is used by SHOW EXPLAIN. It assuses query plan has been already
+ collected into QPF structures and we only need to print it out.
+*/
-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 LEX::print_explain(select_result_sink *output, uint8 explain_flags,
+ bool *printed_anything)
{
int res;
- if (join && join->have_query_plan == JOIN::QEP_AVAILABLE)
+ if (query_plan_footprint && query_plan_footprint->have_query_plan())
{
- /*
- 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;
- }
- }
+ res= query_plan_footprint->print_explain(output, explain_flags);
+ *printed_anything= true;
}
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);
+ res= 0;
+ *printed_anything= false;
}
-err:
return res;
}
-int st_select_lex_unit::print_explain(select_result_sink *output,
- uint8 explain_flags, bool *printed_anything)
+/*
+ Save query plan of a UNION. The only variable member is whether the union has
+ "Using filesort".
+
+ There is also save_union_qpf_part2() function, which is called before we read
+ UNION's output.
+
+ The reason for it is examples like this:
+
+ SELECT col1 FROM t1 UNION SELECT col2 FROM t2 ORDER BY (select ... from t3 ...)
+
+ Here, the (select ... from t3 ...) subquery must be a child of UNION's
+ st_select_lex. However, it is not connected as child until a very late
+ stage in execution.
+*/
+
+int st_select_lex_unit::save_union_qpf(QPF_query *output)
{
- int res= 0;
SELECT_LEX *first= first_select();
-
+ QPF_union *qpfu= new (output->mem_root) QPF_union;
+
+ /*
+ TODO: The following code should be eliminated. If we have a capability to
+ save Query Plan Footprints, we should just save them, and never need to
+ print "query plan already deleted".
+ */
if (first && !first->next_select() && !first->join)
{
/*
@@ -4261,24 +4242,44 @@ int st_select_lex_unit::print_explain(select_result_sink *output,
EXPLAIN state" error.
*/
const char *msg="Query plan already deleted";
- res= print_explain_message_line(output, first, TRUE /* on_the_fly */,
- 0, msg);
+ first->set_explain_type(TRUE/* on_the_fly */);
+
+ QPF_select *qp_sel= new (output->mem_root)QPF_select;
+ qp_sel->select_id= first->select_number;
+ qp_sel->select_type= first->type;
+ qp_sel->message= msg;
+ output->add_node(qp_sel);
+ qpfu->add_select(qp_sel->select_id);
return 0;
}
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
- {
- if ((res= sl->print_explain(output, explain_flags, printed_anything)))
- break;
- }
+ qpfu->add_select(sl->select_number);
- /* Note: fake_select_lex->join may be NULL or non-NULL at this point */
+ // Save the UNION node
+ output->add_node(qpfu);
+
+ qpfu->fake_select_type= "UNION RESULT";
+ qpfu->using_filesort= test(global_parameters->order_list.first);
+ return 0;
+}
+
+
+int st_select_lex_unit::save_union_qpf_part2(QPF_query *output)
+{
+ QPF_union *qpfu= output->get_union(first_select()->select_number);
if (fake_select_lex)
{
- res= print_fake_select_lex_join(output, TRUE /* on the fly */,
- fake_select_lex, explain_flags);
+ for (SELECT_LEX_UNIT *unit= fake_select_lex->first_inner_unit();
+ unit; unit= unit->next_unit())
+ {
+ if (!(unit->item && unit->item->eliminated))
+ {
+ qpfu->add_child(unit->first_select()->select_number);
+ }
+ }
}
- return res;
+ return 0;
}