From 84cb5de047e83ced6ac9490b9da630fe7dff3c4a Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Wed, 24 Aug 2011 14:41:13 +0400 Subject: [PATCH] MWL#182: Explain running statements - Further progress with the code - Testcases. --- mysql-test/r/show_explain.result | 26 ++++++++++++++++++ mysql-test/t/show_explain.test | 46 ++++++++++++++++++++++++++++++++ sql/sql_class.cc | 9 ++++++- sql/sql_lex.cc | 21 +++++++++------ sql/sql_select.cc | 17 +++++++++--- sql/sql_select.h | 1 + 6 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 mysql-test/r/show_explain.result create mode 100644 mysql-test/t/show_explain.test diff --git a/mysql-test/r/show_explain.result b/mysql-test/r/show_explain.result new file mode 100644 index 00000000000..5aee9221d50 --- /dev/null +++ b/mysql-test/r/show_explain.result @@ -0,0 +1,26 @@ +drop table if exists t0, t1; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int); +insert into t1 select A.a + 10*B.a + 100*C.a from t0 A, t0 B, t0 C; +show explain for 2*1000*1000*1000; +ERROR HY000: Unknown thread id: 2000000000 +show explain for 3; +ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command +show explain for 2; +ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command +select get_lock('optimizer_done', 10); +get_lock('optimizer_done', 10) +1 +select count(*) from t1 where a < 100000 and sleep(a*0 + release_lock('optimizer_done') +1); +select get_lock('optimizer_done', 100); +get_lock('optimizer_done', 100) +1 +show explain for 3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 Using where +select release_lock('optimizer_done'); +release_lock('optimizer_done') +1 +kill query 3; +drop table t0,t1; diff --git a/mysql-test/t/show_explain.test b/mysql-test/t/show_explain.test new file mode 100644 index 00000000000..fda31392e46 --- /dev/null +++ b/mysql-test/t/show_explain.test @@ -0,0 +1,46 @@ +# +# Tests for SHOW EXPLAIN FOR functionality +# +--disable_warnings +drop table if exists t0, t1; +--enable_warnings + +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int); +insert into t1 select A.a + 10*B.a + 100*C.a from t0 A, t0 B, t0 C; + +# +# Try killing a non-existent thread +# +--error ER_NO_SUCH_THREAD +show explain for 2*1000*1000*1000; + +# Setup two threads and their ids +let $thr1=`select connection_id()`; +connect (con1, localhost, root,,); +connection con1; +let $thr2=`select connection_id()`; +connection default; + +# SHOW EXPLAIN FOR +--error ER_ERROR_WHEN_EXECUTING_COMMAND +eval show explain for $thr2; + +# SHOW EXPLAIN FOR +--error ER_ERROR_WHEN_EXECUTING_COMMAND +eval show explain for $thr1; + +# SHOW EXPLAIN FOR +connection con1; +select get_lock('optimizer_done', 10); +send select count(*) from t1 where a < 100000 and sleep(a*0 + release_lock('optimizer_done') +1); +connection default; +select get_lock('optimizer_done', 100); +eval show explain for $thr2; +select release_lock('optimizer_done'); +eval kill query $thr2; + +#insert into t1 values ('one'),('two'),('three'); + +drop table t0,t1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 12709e23a34..c9b99b5fd1f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2932,7 +2932,14 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup) DBUG_VOID_RETURN; } -// psergey + +/* + Produce EXPLAIN data. + + This function is APC-scheduled to be run in the context of the thread that + we're producing EXPLAIN for. +*/ + void Show_explain_request::get_explain_data(void *arg) { Show_explain_request *req= (Show_explain_request*)arg; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ae9c11c47e2..454331a0859 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3625,19 +3625,24 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd) int st_select_lex::print_explain(select_result_sink *output) { + int res; if (join && join->optimized == 2) { - //psergey-TODO: any? - return join->print_explain(output, TRUE, - FALSE, // need_tmp_table, - FALSE, // bool need_order, - FALSE, // bool distinct, - NULL); //const char *message + res= join->print_explain(output, TRUE, + FALSE, // need_tmp_table, + FALSE, // bool need_order, + FALSE, // bool distinct, + NULL); //const char *message } else { - DBUG_ASSERT(0); - /* produce "not yet optimized" line */ + /* Produce "not yet optimized" line */ + const char *msg="Not yet optimized"; + res= join->print_explain(output, TRUE, + FALSE, // need_tmp_table, + FALSE, // bool need_order, + FALSE, // bool distinct, + msg); //const char *message } return 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 74d2bc7c356..c3d1543b363 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2019,6 +2019,17 @@ JOIN::save_join_tab() } +void JOIN::exec() +{ + /* + Enable SHOW EXPLAIN only if we're in the top-level query. + */ + thd->apc_target.enable(); + exec_inner(); + thd->apc_target.disable(); +} + + /** Exec select. @@ -2030,8 +2041,8 @@ JOIN::save_join_tab() @todo When can we have here thd->net.report_error not zero? */ -void -JOIN::exec() + +void JOIN::exec_inner() { List *columns_list= &fields_list; int tmp_error; @@ -2894,9 +2905,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, if (thd->is_error()) goto err; - thd->apc_target.enable(); join->exec(); - thd->apc_target.disable(); if (thd->cursor && thd->cursor->is_open()) { diff --git a/sql/sql_select.h b/sql/sql_select.h index e3b6b1f6cac..f329f51707f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1078,6 +1078,7 @@ public: int reinit(); int init_execution(); void exec(); + void exec_inner(); int destroy(); void restore_tmp(); bool alloc_func_list();