From ca020dfa9e8668ce52eaff92c157097bba671ec1 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 28 Oct 2011 02:30:02 +0400 Subject: [PATCH] MWL#182: Explain running statements - Get subqueries to work, part #1. --- mysql-test/r/show_explain.result | 61 ++++++++++++++++++++++++++++ mysql-test/t/show_explain.test | 69 +++++++++++++++++++++++++++++++- sql/sql_lex.cc | 17 ++++++++ sql/sql_select.cc | 11 ++++- 4 files changed, 155 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/show_explain.result b/mysql-test/r/show_explain.result index 9197cc353c6..b8b732f9607 100644 --- a/mysql-test/r/show_explain.result +++ b/mysql-test/r/show_explain.result @@ -64,4 +64,65 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY A ALL NULL NULL NULL NULL 10 2 UNION B ALL NULL NULL NULL NULL 10 NULL UNION RESULT ALL NULL NULL NULL NULL NULL +# Uncorrelated subquery, select +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +select a, (select max(a) from t0 B) from t0 A where a<1; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where +2 SUBQUERY B ALL NULL NULL NULL NULL 10 +a (select max(a) from t0 B) +0 9 +# Uncorrelated subquery, explain +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +explain select a, (select max(a) from t0 B) from t0 A where a<1; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where +2 SUBQUERY B ALL NULL NULL NULL NULL 10 +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where +2 SUBQUERY B ALL NULL NULL NULL NULL 10 +# correlated subquery, select +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where +2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where +a (select max(a) from t0 b where b.a+a.a<10) +0 9 +# correlated subquery, explain +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where +2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where +a (select max(a) from t0 b where b.a+a.a<10) +0 9 +# correlated subquery, select, while inside the subquery +set @show_explain_probe_select_id=2; +set debug='d,show_explain_probe_1'; +select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where +2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where +a (select max(a) from t0 b where b.a+a.a<10) +0 9 +# correlated subquery, explain, while inside the subquery +set @show_explain_probe_select_id=2; +set debug='d,show_explain_probe_1'; +select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +show explain for $thr2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where +2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where +a (select max(a) from t0 b where b.a+a.a<10) +0 9 drop table t0,t1; diff --git a/mysql-test/t/show_explain.test b/mysql-test/t/show_explain.test index 77d79fc78b3..5ed78be1ea4 100644 --- a/mysql-test/t/show_explain.test +++ b/mysql-test/t/show_explain.test @@ -110,6 +110,7 @@ evalp show explain for $thr2; connection con1; reap; + --echo # UNION, second branch set @show_explain_probe_select_id=1; set debug='d,show_explain_probe_1'; @@ -120,7 +121,73 @@ evalp show explain for $thr2; connection con1; reap; -# Let's try with a subquery + +--echo # Uncorrelated subquery, select +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +send select a, (select max(a) from t0 B) from t0 A where a<1; +connection default; +--source include/wait_condition.inc +evalp show explain for $thr2; +connection con1; +reap; + + +--echo # Uncorrelated subquery, explain +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +send explain select a, (select max(a) from t0 B) from t0 A where a<1; +connection default; +--source include/wait_condition.inc +evalp show explain for $thr2; +connection con1; +reap; + +--echo # correlated subquery, select +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +connection default; +--source include/wait_condition.inc +evalp show explain for $thr2; +connection con1; +reap; + +--echo # correlated subquery, explain +set @show_explain_probe_select_id=1; +set debug='d,show_explain_probe_1'; +send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +connection default; +--source include/wait_condition.inc +evalp show explain for $thr2; +connection con1; +reap; + +--echo # correlated subquery, select, while inside the subquery +set @show_explain_probe_select_id=2; # <--- +set debug='d,show_explain_probe_1'; +send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +connection default; +--source include/wait_condition.inc +evalp show explain for $thr2; +connection con1; +reap; + +--echo # correlated subquery, explain, while inside the subquery +set @show_explain_probe_select_id=2; +set debug='d,show_explain_probe_1'; +send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1; +connection default; +--source include/wait_condition.inc +evalp show explain for $thr2; +connection con1; +reap; + + +# TODO: explain in the parent subuqery when the un-correlated child has been +# run (and have done irreversible cleanups) + +# TODO: hit JOIN::optimize for non-select commands: UPDATE/DELETE, SET. ## TODO: Test this: multiple SHOW EXPLAIN calls in course of running of one select diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9aee5caeb64..3b355a312af 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3706,6 +3706,22 @@ int st_select_lex::print_explain(select_result_sink *output) FALSE, // bool need_order, FALSE, // 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)) + { + unit->print_explain(output); + } + } } else { @@ -3717,6 +3733,7 @@ int st_select_lex::print_explain(select_result_sink *output) FALSE, // bool distinct, msg); //const char *message } +err: return 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4dc99cf006c..fcbd2615b9c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -265,7 +265,9 @@ void dbug_serve_apcs(THD *thd, int n_calls) /* - Usage + Debugging: check if @name=value, comparing as integer + + Intended usage: DBUG_EXECUTE_IF("show_explain_probe_2", if (dbug_user_var_equals_int(thd, "select_id", select_id)) @@ -2102,7 +2104,6 @@ void JOIN::exec_inner() int tmp_error; DBUG_ENTER("JOIN::exec"); - DBUG_EXECUTE_IF("show_explain_probe_2", dbug_serve_apcs(thd, 1);); DBUG_EXECUTE_IF("show_explain_probe_1", if (dbug_user_var_equals_int(thd, "show_explain_probe_select_id", @@ -20516,6 +20517,7 @@ void JOIN::clear() } } + int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, SELECT_LEX *select_lex, uint8 select_options) { @@ -20594,6 +20596,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, return 0; } + /** EXPLAIN handling. @@ -21162,6 +21165,10 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly, } +/* + See st_select_lex::print_explain() for the SHOW EXPLAIN counterpart +*/ + static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, bool distinct,const char *message) {