From 103330a3c03bb7c2652129bb87ec085e566aa67a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Oct 2002 00:42:59 +0300 Subject: [PATCH] fixed subselect explain bug mysql-test/r/subselect.result: test for subselect explain bug mysql-test/t/subselect.test: test for subselect explain bug --- mysql-test/r/subselect.result | 24 +++++++-- mysql-test/t/subselect.test | 20 ++++++-- sql/mysql_priv.h | 2 + sql/sql_lex.cc | 2 +- sql/sql_parse.cc | 19 +------ sql/sql_select.cc | 94 ++++++++++++++++++++++++++++------- 6 files changed, 116 insertions(+), 45 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c365c2ed434..2dcafe2c9cb 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -54,9 +54,9 @@ explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 where used +2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort 3 UNION t4 ALL NULL NULL NULL NULL 3 where used; Using filesort 4 SUBSELECT t2 ALL NULL NULL NULL NULL 2 -2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort select (select a from t3 where a &list,COND *conds, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, bool fake_select_lex); void fix_tables_pointers(SELECT_LEX *select_lex); +int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, + select_result *result); int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, select_result *result); int mysql_union(THD *thd, LEX *lex,select_result *result); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 46206079084..9f09afc78a6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -955,6 +955,7 @@ void st_select_lex::init_query() table_list.first= 0; table_list.next= (byte**) &table_list.first; item_list.empty(); + join= 0; } void st_select_lex::init_select() @@ -973,7 +974,6 @@ void st_select_lex::init_select() ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; depended= having_fix_field= 0; - } /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7902e66043d..bb2fe838546 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1484,24 +1484,7 @@ mysql_execute_command(THD *thd) else thd->send_explain_fields(explain_result); fix_tables_pointers(select_lex); - for ( SELECT_LEX *sl= select_lex; - sl && res == 0; - sl= sl->next_select_in_list()) - { - SELECT_LEX *first= sl->master_unit()->first_select(); - res= mysql_explain_select(thd, sl, - ((select_lex==sl)? - ((sl->next_select_in_list())?"PRIMARY": - "SIMPLE"): - ((sl == first)? - ((sl->depended)?"DEPENDENT SUBSELECT": - "SUBSELECT"): - ((sl->depended)?"DEPENDENT UNION": - "UNION"))), - explain_result); - } - if (res > 0) - res= -res; // mysql_explain_select do not report error + res= mysql_explain_union(thd, &thd->lex.unit, explain_result); MYSQL_LOCK *save_lock= thd->lock; thd->lock= (MYSQL_LOCK *)0; explain_result->send_eof(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f7d585e85f8..ac5f922d3a3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -213,7 +213,7 @@ JOIN::prepare(TABLE_LIST *tables_init, SELECT_LEX_UNIT *unit, bool fake_select_lex) { DBUG_ENTER("JOIN::prepare"); - + conds= conds_init; order= order_init; group_list= group_init; @@ -348,7 +348,7 @@ int JOIN::optimize() { DBUG_ENTER("JOIN::optimize"); - + #ifdef HAVE_REF_TO_FIELDS // Not done yet /* Add HAVING to WHERE if possible */ if (having && !group_list && ! sum_func_count) @@ -1018,36 +1018,60 @@ mysql_select(THD *thd, TABLE_LIST *tables, List &fields, COND *conds, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, bool fake_select_lex) { - JOIN *join = new JOIN(thd, fields, select_options, result); - DBUG_ENTER("mysql_select"); - thd->proc_info="init"; - thd->used_tables=0; // Updated by setup_fields - if (join->prepare(tables, conds, order, group, having, proc_param, - select_lex, unit, fake_select_lex)) + bool free_join= 1; + JOIN *join; + if (!fake_select_lex && select_lex->join != 0) { - DBUG_RETURN(-1); + //here is EXPLAIN of subselect or derived table + join= select_lex->join; + join->result= result; + if (!join->procedure && result->prepare(join->fields_list, unit)) + { + DBUG_RETURN(-1); + } + join->select_options= select_options; + free_join= 0; } - switch (join->optimize()) { + else + { + join= new JOIN(thd, fields, select_options, result); + thd->proc_info="init"; + thd->used_tables=0; // Updated by setup_fields + + if (join->prepare(tables, conds, order, group, having, proc_param, + select_lex, unit, fake_select_lex)) + { + DBUG_RETURN(-1); + } + } + + switch (join->optimize()) + { case 1: DBUG_RETURN(join->error); case -1: goto err; - } + } - if (join->global_optimize()) + if (free_join && join->global_optimize()) goto err; join->exec(); err: - thd->limit_found_rows = join->send_records; - thd->examined_row_count = join->examined_rows; - thd->proc_info="end"; - int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error; - delete join; - DBUG_RETURN(error); + if (free_join) + { + thd->limit_found_rows = join->send_records; + thd->examined_row_count = join->examined_rows; + thd->proc_info="end"; + int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error; + delete join; + DBUG_RETURN(error); + } + else + DBUG_RETURN(0); } /***************************************************************************** @@ -7366,9 +7390,43 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, result->send_error(0,NullS); } } + for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit(); + unit; + unit= unit->next_unit()) + { + if (mysql_explain_union(thd, unit, result)) + DBUG_VOID_RETURN; + } DBUG_VOID_RETURN; } +int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) +{ + int res= 0; + SELECT_LEX *first= unit->first_select(); + for (SELECT_LEX *sl= first; + sl; + sl= sl->next_select()) + { + res= mysql_explain_select(thd, sl, + (((&thd->lex.select_lex)==sl)? + ((sl->next_select_in_list())?"PRIMARY": + "SIMPLE"): + ((sl == first)? + ((sl->depended)?"DEPENDENT SUBSELECT": + "SUBSELECT"): + ((sl->depended)?"DEPENDENT UNION": + "UNION"))), + result); + if (res) + break; + + } + if (res > 0) + res= -res; // mysql_explain_select do not report error + return res; +} + int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, select_result *result) {