diff --git a/sql/opt_qpf.cc b/sql/opt_qpf.cc index 12aef844328..90d749ea4b4 100644 --- a/sql/opt_qpf.cc +++ b/sql/opt_qpf.cc @@ -17,6 +17,16 @@ QPF_query::QPF_query() } +QPF_query::~QPF_query() +{ + uint i; + for (i=0 ; i < MAX_TABLES; i++) + delete unions[i]; + for (i=0 ; i < MAX_TABLES; i++) + delete selects[i]; +} + + QPF_node *QPF_query::get_node(uint select_id) { if (unions[select_id]) @@ -178,6 +188,17 @@ int QPF_union::print_explain(QPF_query *query, select_result_sink *output, } +QPF_select::~QPF_select() +{ + if (join_tabs) + { + for (uint i= 0; i< n_join_tabs; i++) + delete join_tabs[i]; + my_free(join_tabs); + } +} + + int QPF_select::print_explain(QPF_query *query, select_result_sink *output, uint8 explain_flags) { @@ -222,6 +243,13 @@ int QPF_select::print_explain(QPF_query *query, select_result_sink *output, } } } + + //psergey-TODO: print children here... + for (int i= 0; i < (int) children.elements(); i++) + { + QPF_node *node= query->get_node(children.at(i)); + node->print_explain(query, output, explain_flags); + } return 0; } @@ -259,7 +287,10 @@ int QPF_table_access::print_explain(select_result_sink *output, uint8 explain_fl /* `possible_keys` column */ //push_str(item_list, "TODO"); - item_list.push_back(item_null); + if (possible_keys_str.length() > 0) + push_string(&item_list, &possible_keys_str); + else + item_list.push_back(item_null); /* `key` */ if (key_set) diff --git a/sql/opt_qpf.h b/sql/opt_qpf.h index 86655f3ed3d..6aa0a5327da 100644 --- a/sql/opt_qpf.h +++ b/sql/opt_qpf.h @@ -48,33 +48,19 @@ class QPF_select : public QPF_node public: enum qpf_node_type get_type() { return QPF_SELECT; } -#if 0 - /* Constructs a finished degenerate join plan */ - QPF_select(int select_id_arg, const char *select_type_arg, const char* msg) : - select_id(select_id_arg), - select_type(select_type_arg), - message(msg), - join_tabs(NULL), n_join_tabs(0) - {} - - /* Constructs an un-finished, non degenerate join plan. */ - QPF_select(int select_id_arg, const char *select_type_arg) : - select_id(select_id_arg), - select_type(select_type_arg), - message(NULL), - join_tabs(NULL), n_join_tabs(0) - {} -#endif QPF_select() : message(NULL), join_tabs(NULL), using_temporary(false), using_filesort(false) {} + + ~QPF_select(); bool add_table(QPF_table_access *tab) { if (!join_tabs) { - join_tabs= (QPF_table_access**) malloc(sizeof(QPF_table_access*) * MAX_TABLES); + join_tabs= (QPF_table_access**) my_malloc(sizeof(QPF_table_access*) * + MAX_TABLES, MYF(0)); n_join_tabs= 0; } join_tabs[n_join_tabs++]= tab; @@ -103,6 +89,13 @@ public: /* Global join attributes. In tabular form, they are printed on the first row */ bool using_temporary; bool using_filesort; + + /* Child selects. TODO: join this with QPF_union's children? */ + Dynamic_array children; + void add_child(int select_no) + { + children.append(select_no); + } void print_tabular(select_result_sink *output, uint8 explain_flags//, //bool *printed_anything @@ -143,10 +136,11 @@ public: This is the whole query. */ -class QPF_query +class QPF_query : public Sql_alloc { public: QPF_query(); + ~QPF_query(); void add_node(QPF_node *node); int print_explain(select_result_sink *output, uint8 explain_flags); @@ -203,7 +197,7 @@ enum Extra_tag }; -class QPF_table_access +class QPF_table_access : public Sql_alloc { public: void push_extra(enum Extra_tag extra_tag); @@ -220,6 +214,7 @@ public: bool used_partitions_set; key_map possible_keys; + StringBuffer<256> possible_keys_str; uint key_no; uint key_length; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index aab26e72a65..d6e31f4142c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4814,7 +4814,12 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) thd->lex->query_plan_footprint= new QPF_query; res= mysql_explain_union(thd, &thd->lex->unit, result); - thd->lex->query_plan_footprint->print_explain(result, thd->lex->describe); + if (!res) + { + thd->lex->query_plan_footprint->print_explain(result, thd->lex->describe); + } + delete thd->lex->query_plan_footprint; + thd->lex->query_plan_footprint= NULL; //psergey-todo: here, produce the EXPLAIN output. // mysql_explain_union() itself is only responsible for calling diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 45090a2cec5..09c28680860 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -22903,6 +22903,21 @@ void QPF_table_access::push_extra(enum Extra_tag extra_tag) extra_tags.append(extra_tag); } +void append_possible_keys(String *str, TABLE *table, key_map possible_keys) +{ + uint j; + for (j=0 ; j < table->s->keys ; j++) + { + if (possible_keys.is_set(j)) + { + if (str->length()) + str->append(','); + str->append(table->key_info[j].name, + strlen(table->key_info[j].name), + system_charset_info); + } + } +} /* Save Query Plan Footprint @@ -22982,9 +22997,6 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, for (JOIN_TAB *tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS); tab; tab= next_breadth_first_tab(join, WALK_OPTIMIZATION_TABS, tab)) { - QPF_table_access *qpt= new QPF_table_access; - qp_sel->add_table(qpt); - if (tab->bush_root_tab) { JOIN_TAB *first_sibling= tab->bush_root_tab->bush_children->start; @@ -23020,7 +23032,6 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, continue; } - if (join->table_access_tabs == join->join_tab && tab == (first_top_tab + join->const_tables) && pre_sort_join_tab) { @@ -23028,8 +23039,12 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, tab= pre_sort_join_tab; } + QPF_table_access *qpt= new QPF_table_access; + qp_sel->add_table(qpt); + /* id */ - qp_sel->select_id= select_id; + // TODO: this can be '2' in case of SJM nests.. + //qp_sel->select_id= select_id; /* select_type */ //const char* stype= printing_materialize_nest? "MATERIALIZED" : @@ -23099,6 +23114,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, /* Build "possible_keys" value */ qpt->possible_keys= tab->keys; + append_possible_keys(&qpt->possible_keys_str, table, tab->keys); /* Build "key", "key_len", and "ref" */ @@ -23379,9 +23395,10 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, */ if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE) { - qpt->push_extra(ET_USING_MRR); explain_append_mrr_info((QUICK_RANGE_SELECT*)(tab->select->quick), &qpt->mrr_type); + if (qpt->mrr_type.length() > 0) + qpt->push_extra(ET_USING_MRR); } if (need_tmp_table) @@ -23463,6 +23480,23 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, } output->add_node(qp_sel); } + + + /// + 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)) + { + qp_sel->add_child(unit->first_select()->select_number); + } + } + DBUG_RETURN(error); }