diff options
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/log_event.cc | 2 | ||||
-rw-r--r-- | sql/opt_qpf.cc | 102 | ||||
-rw-r--r-- | sql/opt_qpf.h | 130 | ||||
-rw-r--r-- | sql/opt_range.cc | 35 | ||||
-rw-r--r-- | sql/opt_range.h | 16 | ||||
-rw-r--r-- | sql/sp_head.cc | 6 | ||||
-rw-r--r-- | sql/sql_delete.cc | 16 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 10 | ||||
-rw-r--r-- | sql/sql_join_cache.h | 8 | ||||
-rw-r--r-- | sql/sql_lex.cc | 50 | ||||
-rw-r--r-- | sql/sql_lex.h | 22 | ||||
-rw-r--r-- | sql/sql_parse.cc | 17 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 101 | ||||
-rw-r--r-- | sql/sql_select.h | 16 | ||||
-rw-r--r-- | sql/sql_union.cc | 8 | ||||
-rw-r--r-- | sql/sql_update.cc | 8 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 5 |
19 files changed, 273 insertions, 289 deletions
diff --git a/sql/log.cc b/sql/log.cc index 3f782a478bb..7d39a27549a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2826,11 +2826,11 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, thd->query_plan_fsort_passes) == (size_t) -1) tmp_errno= errno; if (thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_EXPLAIN && - thd->lex->query_plan_footprint) + thd->lex->explain) { StringBuffer<128> buf; DBUG_ASSERT(!thd->free_list); - if (!print_qpf_query(thd->lex, thd, &buf)) + if (!print_explain_query(thd->lex, thd, &buf)) my_b_printf(&log_file, "%s", buf.c_ptr_safe()); thd->free_items(); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 7ebcc6892e5..ca083711c40 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9151,7 +9151,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) call might reset the value of current_stmt_binlog_format, so we need to do any changes to that value after this function. */ - delete_qpf_query(thd->lex); + delete_explain_query(thd->lex); lex_start(thd); mysql_reset_thd_for_next_command(thd, 0); /* diff --git a/sql/opt_qpf.cc b/sql/opt_qpf.cc index 43c00573c2d..248dc2b12be 100644 --- a/sql/opt_qpf.cc +++ b/sql/opt_qpf.cc @@ -22,14 +22,14 @@ #include "sql_select.h" -QPF_query::QPF_query() +Explain_query::Explain_query() { upd_del_plan= NULL; operations= 0; } -QPF_query::~QPF_query() +Explain_query::~Explain_query() { delete upd_del_plan; uint i; @@ -40,37 +40,37 @@ QPF_query::~QPF_query() } -QPF_node *QPF_query::get_node(uint select_id) +Explain_node *Explain_query::get_node(uint select_id) { - QPF_union *u; + Explain_union *u; if ((u= get_union(select_id))) return u; else return get_select(select_id); } -QPF_union *QPF_query::get_union(uint select_id) +Explain_union *Explain_query::get_union(uint select_id) { return (unions.elements() > select_id) ? unions.at(select_id) : NULL; } -QPF_select *QPF_query::get_select(uint select_id) +Explain_select *Explain_query::get_select(uint select_id) { return (selects.elements() > select_id) ? selects.at(select_id) : NULL; } -void QPF_query::add_node(QPF_node *node) +void Explain_query::add_node(Explain_node *node) { operations++; - if (node->get_type() == QPF_node::QPF_UNION) + if (node->get_type() == Explain_node::EXPLAIN_UNION) { - QPF_union *u= (QPF_union*)node; + Explain_union *u= (Explain_union*)node; uint select_id= u->get_select_id(); if (unions.elements() <= select_id) unions.resize(max(select_id+1, unions.elements()*2), NULL); - QPF_union *old_node; + Explain_union *old_node; if ((old_node= get_union(select_id))) delete old_node; @@ -78,15 +78,15 @@ void QPF_query::add_node(QPF_node *node) } else { - QPF_select *sel= (QPF_select*)node; - if (sel->select_id == (int)UINT_MAX) + Explain_select *sel= (Explain_select*)node; + if (sel->select_id == FAKE_SELECT_LEX_ID) { DBUG_ASSERT(0); // this is a "fake select" from a UNION. } else { uint select_id= sel->select_id; - QPF_select *old_node; + Explain_select *old_node; if (selects.elements() <= select_id) selects.resize(max(select_id+1, selects.elements()*2), NULL); @@ -104,7 +104,7 @@ void QPF_query::add_node(QPF_node *node) The main entry point to print EXPLAIN of the entire query */ -int QPF_query::print_explain(select_result_sink *output, +int Explain_query::print_explain(select_result_sink *output, uint8 explain_flags) { if (upd_del_plan) @@ -115,7 +115,7 @@ int QPF_query::print_explain(select_result_sink *output, else { /* Start printing from node with id=1 */ - QPF_node *node= get_node(1); + Explain_node *node= get_node(1); if (!node) return 1; /* No query plan */ return node->print_explain(this, output, explain_flags); @@ -123,13 +123,13 @@ int QPF_query::print_explain(select_result_sink *output, } -bool print_qpf_query(LEX *lex, THD *thd, String *str) +bool print_explain_query(LEX *lex, THD *thd, String *str) { - return lex->query_plan_footprint->print_explain_str(thd, str); + return lex->explain->print_explain_str(thd, str); } -bool QPF_query::print_explain_str(THD *thd, String *out_str) +bool Explain_query::print_explain_str(THD *thd, String *out_str) { List<Item> fields; thd->make_explain_field_list(fields); @@ -157,13 +157,14 @@ static void push_string(List<Item> *item_list, String *str) } -int QPF_union::print_explain(QPF_query *query, select_result_sink *output, - uint8 explain_flags) +int Explain_union::print_explain(Explain_query *query, + select_result_sink *output, + uint8 explain_flags) { /* print all UNION children, in order */ for (int i= 0; i < (int) union_members.elements(); i++) { - QPF_select *sel= query->get_select(union_members.at(i)); + Explain_select *sel= query->get_select(union_members.at(i)); sel->print_explain(query, output, explain_flags); } @@ -257,13 +258,13 @@ int QPF_union::print_explain(QPF_query *query, select_result_sink *output, Print EXPLAINs for all children nodes (i.e. for subqueries) */ -int QPF_node::print_explain_for_children(QPF_query *query, +int Explain_node::print_explain_for_children(Explain_query *query, select_result_sink *output, uint8 explain_flags) { for (int i= 0; i < (int) children.elements(); i++) { - QPF_node *node= query->get_node(children.at(i)); + Explain_node *node= query->get_node(children.at(i)); if (node->print_explain(query, output, explain_flags)) return 1; } @@ -271,7 +272,7 @@ int QPF_node::print_explain_for_children(QPF_query *query, } -QPF_select::~QPF_select() +Explain_select::~Explain_select() { if (join_tabs) { @@ -282,8 +283,9 @@ QPF_select::~QPF_select() } -int QPF_select::print_explain(QPF_query *query, select_result_sink *output, - uint8 explain_flags) +int Explain_select::print_explain(Explain_query *query, + select_result_sink *output, + uint8 explain_flags) { if (message) { @@ -330,13 +332,13 @@ int QPF_select::print_explain(QPF_query *query, select_result_sink *output, } -void QPF_table_access::push_extra(enum Extra_tag extra_tag) +void Explain_table_access::push_extra(enum explain_extra_tag extra_tag) { extra_tags.append(extra_tag); } -int QPF_table_access::print_explain(select_result_sink *output, uint8 explain_flags, +int Explain_table_access::print_explain(select_result_sink *output, uint8 explain_flags, uint select_id, const char *select_type, bool using_temporary, bool using_filesort) { @@ -551,7 +553,7 @@ const char * extra_tag_text[]= }; -void QPF_table_access::append_tag_name(String *str, enum Extra_tag tag) +void Explain_table_access::append_tag_name(String *str, enum explain_extra_tag tag) { switch (tag) { case ET_USING: @@ -618,13 +620,13 @@ void QPF_table_access::append_tag_name(String *str, enum Extra_tag tag) /* - This is called for top-level QPF_quick_select only. The point of this + This is called for top-level Explain_quick_select only. The point of this function is: - index_merge should print $index_merge_type (child, ...) - 'range' should not print anything. */ -void QPF_quick_select::print_extra(String *str) +void Explain_quick_select::print_extra(String *str) { if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE || quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC || @@ -637,7 +639,7 @@ void QPF_quick_select::print_extra(String *str) } -void QPF_quick_select::print_extra_recursive(String *str) +void Explain_quick_select::print_extra_recursive(String *str) { if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE || quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC) @@ -648,8 +650,8 @@ void QPF_quick_select::print_extra_recursive(String *str) { str->append(get_name_by_type()); str->append('('); - List_iterator_fast<QPF_quick_select> it (children); - QPF_quick_select* child; + List_iterator_fast<Explain_quick_select> it (children); + Explain_quick_select* child; bool first= true; while ((child = it++)) { @@ -665,7 +667,7 @@ void QPF_quick_select::print_extra_recursive(String *str) } -const char * QPF_quick_select::get_name_by_type() +const char * Explain_quick_select::get_name_by_type() { switch (quick_type) { case QUICK_SELECT_I::QS_TYPE_INDEX_MERGE: @@ -687,7 +689,7 @@ const char * QPF_quick_select::get_name_by_type() This prints a comma-separated list of used indexes, ignoring nesting */ -void QPF_quick_select::print_key(String *str) +void Explain_quick_select::print_key(String *str) { if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE || quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC || @@ -699,8 +701,8 @@ void QPF_quick_select::print_key(String *str) } else { - List_iterator_fast<QPF_quick_select> it (children); - QPF_quick_select* child; + List_iterator_fast<Explain_quick_select> it (children); + Explain_quick_select* child; while ((child = it++)) { child->print_key(str); @@ -713,7 +715,7 @@ void QPF_quick_select::print_key(String *str) This prints a comma-separated list of used key_lengths, ignoring nesting */ -void QPF_quick_select::print_key_len(String *str) +void Explain_quick_select::print_key_len(String *str) { if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE || quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC || @@ -728,8 +730,8 @@ void QPF_quick_select::print_key_len(String *str) } else { - List_iterator_fast<QPF_quick_select> it (children); - QPF_quick_select* child; + List_iterator_fast<Explain_quick_select> it (children); + Explain_quick_select* child; while ((child = it++)) { child->print_key_len(str); @@ -738,7 +740,7 @@ void QPF_quick_select::print_key_len(String *str) } -int QPF_delete::print_explain(QPF_query *query, select_result_sink *output, +int QPF_delete::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags) { if (deleting_all_rows) @@ -757,7 +759,7 @@ int QPF_delete::print_explain(QPF_query *query, select_result_sink *output, } -int QPF_update::print_explain(QPF_query *query, select_result_sink *output, +int QPF_update::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags) { StringBuffer<64> extra_str; @@ -809,18 +811,18 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output, } -void delete_qpf_query(LEX *lex) +void delete_explain_query(LEX *lex) { - delete lex->query_plan_footprint; - lex->query_plan_footprint= NULL; + delete lex->explain; + lex->explain= NULL; } -void create_qpf_query(LEX *lex, MEM_ROOT *mem_root) +void create_explain_query(LEX *lex, MEM_ROOT *mem_root) { - DBUG_ASSERT(!lex->query_plan_footprint); - lex->query_plan_footprint= new QPF_query; + DBUG_ASSERT(!lex->explain); + lex->explain= new Explain_query; DBUG_ASSERT(mem_root == current_thd->mem_root); - lex->query_plan_footprint->mem_root= mem_root; + lex->explain->mem_root= mem_root; } diff --git a/sql/opt_qpf.h b/sql/opt_qpf.h index d22135dcec0..ef36cb4a44d 100644 --- a/sql/opt_qpf.h +++ b/sql/opt_qpf.h @@ -17,33 +17,35 @@ /************************************************************************************** - Query Plan Footprint (QPF) structures + Data structures for producing EXPLAIN outputs. These structures - - Can be produced in-expensively from query plan. - - Store sufficient information to produce either a tabular or a json EXPLAIN - output + - Can be produced inexpensively from query plan. + - Store sufficient information to produce a tabular and/or a json EXPLAIN - Have methods that produce a tabular output. - + *************************************************************************************/ -class QPF_query; + +const int FAKE_SELECT_LEX_ID= (int)UINT_MAX; + +class Explain_query; /* A node can be either a SELECT, or a UNION. */ -class QPF_node : public Sql_alloc +class Explain_node : public Sql_alloc { public: - enum qpf_node_type {QPF_UNION, QPF_SELECT, QPF_UPDATE, QPF_DELETE }; - virtual enum qpf_node_type get_type()= 0; + enum explain_node_type {EXPLAIN_UNION, EXPLAIN_SELECT, EXPLAIN_UPDATE, EXPLAIN_DELETE }; + virtual enum explain_node_type get_type()= 0; virtual int get_select_id()= 0; /* - A node may have children nodes. When a node's QPF (Query Plan Footprint) is - created, children nodes may not yet have QPFs. This is why we store ids. + A node may have children nodes. When a node's explain structure is + created, children nodes may not yet have QPFs. This is why we store ids. */ Dynamic_array<int> children; void add_child(int select_no) @@ -51,20 +53,20 @@ public: children.append(select_no); } - virtual int print_explain(QPF_query *query, select_result_sink *output, + virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags)=0; - int print_explain_for_children(QPF_query *query, select_result_sink *output, + int print_explain_for_children(Explain_query *query, select_result_sink *output, uint8 explain_flags); - virtual ~QPF_node(){} + virtual ~Explain_node(){} }; -class QPF_table_access; +class Explain_table_access; /* - Query Plan Footprint of a SELECT. + EXPLAIN structure for a SELECT. A select can be: 1. A degenerate case. In this case, message!=NULL, and it contains a @@ -74,27 +76,27 @@ class QPF_table_access; In the non-degenerate case, a SELECT may have a GROUP BY/ORDER BY operation. - In both cases, the select may have children nodes. class QPF_node provides + In both cases, the select may have children nodes. class Explain_node provides a way get node's children. */ -class QPF_select : public QPF_node +class Explain_select : public Explain_node { public: - enum qpf_node_type get_type() { return QPF_SELECT; } + enum explain_node_type get_type() { return EXPLAIN_SELECT; } - QPF_select() : + Explain_select() : message(NULL), join_tabs(NULL), using_temporary(false), using_filesort(false) {} - ~QPF_select(); + ~Explain_select(); - bool add_table(QPF_table_access *tab) + bool add_table(Explain_table_access *tab) { if (!join_tabs) { - join_tabs= (QPF_table_access**) my_malloc(sizeof(QPF_table_access*) * + join_tabs= (Explain_table_access**) my_malloc(sizeof(Explain_table_access*) * MAX_TABLES, MYF(0)); n_join_tabs= 0; } @@ -115,31 +117,31 @@ public: const char *message; /* - A flat array of Query Plan Footprints. The order is "just like EXPLAIN + A flat array of Explain structs for tables. The order is "just like EXPLAIN would print them". */ - QPF_table_access** join_tabs; + Explain_table_access** join_tabs; uint n_join_tabs; /* Global join attributes. In tabular form, they are printed on the first row */ bool using_temporary; bool using_filesort; - int print_explain(QPF_query *query, select_result_sink *output, + int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags); }; /* - Query Plan Footprint of a UNION. + Explain structure for a UNION. A UNION may or may not have "Using filesort". */ -class QPF_union : public QPF_node +class Explain_union : public Explain_node { public: - enum qpf_node_type get_type() { return QPF_UNION; } + enum explain_node_type get_type() { return EXPLAIN_UNION; } int get_select_id() { @@ -163,7 +165,7 @@ public: { union_members.append(select_no); } - int print_explain(QPF_query *query, select_result_sink *output, + int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags); const char *fake_select_type; @@ -174,7 +176,7 @@ class QPF_delete; /* - Query Plan Footprint (QPF) for a query (i.e. a statement). + Explain structure for a query (i.e. a statement). This should be able to survive when the query plan was deleted. Currently, we do not intend for it survive until after query's MEM_ROOT is freed. It @@ -208,21 +210,21 @@ class QPF_delete; */ -class QPF_query : public Sql_alloc +class Explain_query : public Sql_alloc { public: - QPF_query(); - ~QPF_query(); + Explain_query(); + ~Explain_query(); /* Add a new node */ - void add_node(QPF_node *node); + void add_node(Explain_node *node); /* This will return a select, or a union */ - QPF_node *get_node(uint select_id); + Explain_node *get_node(uint select_id); /* This will return a select (even if there is a union with this id) */ - QPF_select *get_select(uint select_id); + Explain_select *get_select(uint select_id); - QPF_union *get_union(uint select_id); + Explain_union *get_union(uint select_id); /* QPF_delete inherits from QPF_update */ QPF_update *upd_del_plan; @@ -237,8 +239,8 @@ public: bool have_query_plan() { return upd_del_plan!= NULL || get_node(1) != NULL; } MEM_ROOT *mem_root; private: - Dynamic_array<QPF_union*> unions; - Dynamic_array<QPF_select*> selects; + Dynamic_array<Explain_union*> unions; + Dynamic_array<Explain_select*> selects; /* Debugging aid: count how many times add_node() was called. Ideally, it @@ -252,10 +254,10 @@ private: /* Some of the tags have matching text. See extra_tag_text for text names, and - QPF_table_access::append_tag_name() for code to convert from tag form to text + Explain_table_access::append_tag_name() for code to convert from tag form to text form. */ -enum Extra_tag +enum explain_extra_tag { ET_none= 0, /* not-a-tag */ ET_USING_INDEX_CONDITION, @@ -296,19 +298,19 @@ enum Extra_tag }; -typedef struct st_qpf_bka_type +typedef struct st_explain_bka_type { bool incremental; const char *join_alg; StringBuffer<64> mrr_type; -} QPF_BKA_TYPE; +} EXPLAIN_BKA_TYPE; /* Data about how an index is used by some access method */ -class QPF_index_use : public Sql_alloc +class Explain_index_use : public Sql_alloc { char *key_name; uint key_len; @@ -336,16 +338,16 @@ public: /* QPF for quick range selects, as well as index_merge select */ -class QPF_quick_select : public Sql_alloc +class Explain_quick_select : public Sql_alloc { public: int quick_type; /* This is used when quick_type == QUICK_SELECT_I::QS_TYPE_RANGE */ - QPF_index_use range; + Explain_index_use range; /* Used in all other cases */ - List<QPF_quick_select> children; + List<Explain_quick_select> children; void print_extra(String *str); void print_key(String *str); @@ -359,20 +361,20 @@ private: /* Query Plan Footprint for a JOIN_TAB. */ -class QPF_table_access : public Sql_alloc +class Explain_table_access : public Sql_alloc { public: - void push_extra(enum Extra_tag extra_tag); + void push_extra(enum explain_extra_tag extra_tag); /* Internals */ public: /* - 0 means this tab is not inside SJM nest and should use QPF_select's id + 0 means this tab is not inside SJM nest and should use Explain_select's id other value means the tab is inside an SJM nest. */ int sjm_nest_select_id; - /* id and 'select_type' are cared-of by the parent QPF_select */ + /* id and 'select_type' are cared-of by the parent Explain_select */ StringBuffer<32> table_name; enum join_type type; @@ -391,13 +393,13 @@ public: key.key_name == NULL means 'NULL' will be shown in tabular output. key.key_len == (uint)-1 means 'NULL' will be shown in tabular output. */ - QPF_index_use key; + Explain_index_use key; /* when type==JT_HASH_NEXT, 'key' stores the hash join pseudo-key. hash_next_key stores the table's key. */ - QPF_index_use hash_next_key; + Explain_index_use hash_next_key; bool ref_set; /* not set means 'NULL' should be printed */ StringBuffer<32> ref; @@ -412,10 +414,10 @@ public: Contents of the 'Extra' column. Some are converted into strings, some have parameters, values for which are stored below. */ - Dynamic_array<enum Extra_tag> extra_tags; + Dynamic_array<enum explain_extra_tag> extra_tags; // Valid if ET_USING tag is present - QPF_quick_select *quick_info; + Explain_quick_select *quick_info; // Valid if ET_USING_INDEX_FOR_GROUP_BY is present bool loose_scan_is_scanning; @@ -427,7 +429,7 @@ public: StringBuffer<32> mrr_type; // valid with ET_USING_JOIN_BUFFER - QPF_BKA_TYPE bka_type; + EXPLAIN_BKA_TYPE bka_type; StringBuffer<32> firstmatch_table_name; @@ -435,21 +437,21 @@ public: uint select_id, const char *select_type, bool using_temporary, bool using_filesort); private: - void append_tag_name(String *str, enum Extra_tag tag); + void append_tag_name(String *str, enum explain_extra_tag tag); }; /* Query Plan Footprint for single-table UPDATE. - This is similar to QPF_table_access, except that it is more restrictive. + This is similar to Explain_table_access, except that it is more restrictive. Also, it can have UPDATE operation options, but currently there aren't any. */ -class QPF_update : public QPF_node +class QPF_update : public Explain_node { public: - virtual enum qpf_node_type get_type() { return QPF_UPDATE; } + virtual enum explain_node_type get_type() { return EXPLAIN_UPDATE; } virtual int get_select_id() { return 1; /* always root */ } const char *select_type; @@ -471,7 +473,7 @@ public: bool using_filesort; - virtual int print_explain(QPF_query *query, select_result_sink *output, + virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags); }; @@ -489,10 +491,10 @@ public: */ bool deleting_all_rows; - virtual enum qpf_node_type get_type() { return QPF_DELETE; } + virtual enum explain_node_type get_type() { return EXPLAIN_DELETE; } virtual int get_select_id() { return 1; /* always root */ } - virtual int print_explain(QPF_query *query, select_result_sink *output, + virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags); }; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 97cbe73dcb4..2e32009bc54 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11940,37 +11940,39 @@ void QUICK_SELECT_I::add_key_name(String *str, bool *first) } -void QUICK_RANGE_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) +void QUICK_RANGE_SELECT::save_info(MEM_ROOT *alloc, Explain_quick_select *qpf) { qpf->quick_type= QS_TYPE_RANGE; qpf->range.set(alloc, head->key_info[index].name, max_used_key_length); } -void QUICK_GROUP_MIN_MAX_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) +void QUICK_GROUP_MIN_MAX_SELECT::save_info(MEM_ROOT *alloc, + Explain_quick_select *qpf) { qpf->quick_type= QS_TYPE_GROUP_MIN_MAX; qpf->range.set(alloc, head->key_info[index].name, max_used_key_length); } -void QUICK_INDEX_SORT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) +void QUICK_INDEX_SORT_SELECT::save_info(MEM_ROOT *alloc, + Explain_quick_select *qpf) { qpf->quick_type= get_type(); QUICK_RANGE_SELECT *quick; - QPF_quick_select *child_qpf; + Explain_quick_select *child_qpf; List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); while ((quick= it++)) { - child_qpf= new QPF_quick_select; + child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); quick->save_info(alloc, child_qpf); } if (pk_quick_select) { - child_qpf= new QPF_quick_select; + child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); pk_quick_select->save_info(alloc, child_qpf); } @@ -11980,14 +11982,15 @@ void QUICK_INDEX_SORT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) Same as QUICK_INDEX_SORT_SELECT::save_info(), but primary key is printed first */ -void QUICK_INDEX_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) +void QUICK_INDEX_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, + Explain_quick_select *qpf) { qpf->quick_type= get_type(); - QPF_quick_select *child_qpf; + Explain_quick_select *child_qpf; if (pk_quick_select) { - child_qpf= new QPF_quick_select; + child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); pk_quick_select->save_info(alloc, child_qpf); } @@ -11996,7 +11999,7 @@ void QUICK_INDEX_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select * List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); while ((quick= it++)) { - child_qpf= new QPF_quick_select; + child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); quick->save_info(alloc, child_qpf); } @@ -12004,7 +12007,8 @@ void QUICK_INDEX_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select * } -void QUICK_ROR_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) +void QUICK_ROR_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, + Explain_quick_select *qpf) { qpf->quick_type= get_type(); @@ -12012,21 +12016,22 @@ void QUICK_ROR_INTERSECT_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qp List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects); while ((qr= it++)) { - QPF_quick_select *child_qpf= new QPF_quick_select; + Explain_quick_select *child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); qr->quick->save_info(alloc, child_qpf); } if (cpk_quick) { - QPF_quick_select *child_qpf= new QPF_quick_select; + Explain_quick_select *child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); cpk_quick->save_info(alloc, child_qpf); } } -void QUICK_ROR_UNION_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) +void QUICK_ROR_UNION_SELECT::save_info(MEM_ROOT *alloc, + Explain_quick_select *qpf) { qpf->quick_type= get_type(); @@ -12034,7 +12039,7 @@ void QUICK_ROR_UNION_SELECT::save_info(MEM_ROOT *alloc, QPF_quick_select *qpf) List_iterator_fast<QUICK_SELECT_I> it(quick_selects); while ((quick= it++)) { - QPF_quick_select *child_qpf= new QPF_quick_select; + Explain_quick_select *child_qpf= new Explain_quick_select; qpf->children.push_back(child_qpf); quick->save_info(alloc, child_qpf); } diff --git a/sql/opt_range.h b/sql/opt_range.h index f2e8b92e7d0..9bc19927fd0 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -52,7 +52,7 @@ typedef struct st_key_part { Field::imagetype image_type; } KEY_PART; -class QPF_quick_select; +class Explain_quick_select; /* A "MIN_TUPLE < tbl.key_tuple < MAX_TUPLE" interval. @@ -346,7 +346,7 @@ public: void add_key_name(String *str, bool *first); /* Save information about quick select's query plan */ - virtual void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf)= 0; + virtual void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf)= 0; /* Return 1 if any index used by this quick select @@ -473,7 +473,7 @@ public: { file->position(record); } int get_type() { return QS_TYPE_RANGE; } void add_keys_and_lengths(String *key_names, String *used_lengths); - void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf); + void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -610,7 +610,7 @@ public: #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif - void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf); + void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf); bool push_quick_back(QUICK_RANGE_SELECT *quick_sel_range); @@ -674,7 +674,7 @@ public: int get_next(); int get_type() { return QS_TYPE_INDEX_INTERSECT; } void add_keys_and_lengths(String *key_names, String *used_lengths); - void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf); + void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf); }; @@ -712,7 +712,7 @@ public: bool unique_key_range() { return false; } int get_type() { return QS_TYPE_ROR_INTERSECT; } void add_keys_and_lengths(String *key_names, String *used_lengths); - void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf); + void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf); bool is_keys_used(const MY_BITMAP *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); @@ -791,7 +791,7 @@ public: bool unique_key_range() { return false; } int get_type() { return QS_TYPE_ROR_UNION; } void add_keys_and_lengths(String *key_names, String *used_lengths); - void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf); + void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf); bool is_keys_used(const MY_BITMAP *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); @@ -940,7 +940,7 @@ public: #endif bool is_agg_distinct() { return have_agg_distinct; } bool loose_scan_is_scanning() { return is_index_scan; } - void save_info(MEM_ROOT *alloc, QPF_quick_select *qpf); + void save_info(MEM_ROOT *alloc, Explain_quick_select *qpf); }; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a3027763b8a..31fd0d7248e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3034,7 +3034,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, thd->mdl_context.release_statement_locks(); } - delete_qpf_query(m_lex); + delete_explain_query(m_lex); if (m_lex->query_tables_own_last) { @@ -3242,7 +3242,7 @@ sp_instr_set::execute(THD *thd, uint *nextp) int sp_instr_set::exec_core(THD *thd, uint *nextp) { - create_qpf_query(thd->lex, thd->mem_root); + create_explain_query(thd->lex, thd->mem_root); int res= thd->spcont->set_variable(thd, m_offset, &m_value); if (res) @@ -3255,7 +3255,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); } } - delete_qpf_query(thd->lex); + delete_explain_query(thd->lex); *nextp = m_ip+1; return res; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index adc998be3a1..58deae4162a 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -51,7 +51,7 @@ invoked on a running DELETE statement. */ -void Delete_plan::save_qpf(QPF_query *query) +void Delete_plan::save_explain_data(Explain_query *query) { QPF_delete* qpf= new QPF_delete; @@ -63,22 +63,22 @@ void Delete_plan::save_qpf(QPF_query *query) else { qpf->deleting_all_rows= false; - Update_plan::save_qpf_intern(query, qpf); + Update_plan::save_explain_data_intern(query, qpf); } query->upd_del_plan= qpf; } -void Update_plan::save_qpf(QPF_query *query) +void Update_plan::save_explain_data(Explain_query *query) { QPF_update* qpf= new QPF_update; - save_qpf_intern(query, qpf); + save_explain_data_intern(query, qpf); query->upd_del_plan= qpf; } -void Update_plan::save_qpf_intern(QPF_query *query, QPF_update *qpf) +void Update_plan::save_explain_data_intern(Explain_query *query, QPF_update *qpf) { qpf->select_type= "SIMPLE"; qpf->table_name.append(table->pos_in_table_list->alias); @@ -434,7 +434,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (thd->lex->describe) goto exit_without_my_ok; - query_plan.save_qpf(thd->lex->query_plan_footprint); + query_plan.save_explain_data(thd->lex->explain); thd->apc_target.enable(); DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start", @@ -667,7 +667,7 @@ cleanup: /* Special exits */ exit_without_my_ok: - query_plan.save_qpf(thd->lex->query_plan_footprint); + query_plan.save_explain_data(thd->lex->explain); select_send *result2; if (!(result2= new select_send())) @@ -675,7 +675,7 @@ exit_without_my_ok: List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */ result2->prepare(dummy, &thd->lex->unit); thd->send_explain_fields(result2); - int err2= thd->lex->query_plan_footprint->print_explain(result2, thd->lex->describe); + int err2= thd->lex->explain->print_explain(result2, thd->lex->describe); if (err2) result2->abort_result_set(); diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 7710db5c7ba..040e596d283 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -2568,7 +2568,7 @@ finish: none */ -void JOIN_CACHE::save_qpf(struct st_qpf_bka_type *qpf) +void JOIN_CACHE::save_explain_data(struct st_explain_bka_type *qpf) { qpf->incremental= test(prev_cache); @@ -2613,16 +2613,16 @@ static void add_mrr_explain_info(String *str, uint mrr_mode, handler *file) } } -void JOIN_CACHE_BKA::save_qpf(struct st_qpf_bka_type *qpf) +void JOIN_CACHE_BKA::save_explain_data(struct st_explain_bka_type *qpf) { - JOIN_CACHE::save_qpf(qpf); + JOIN_CACHE::save_explain_data(qpf); add_mrr_explain_info(&qpf->mrr_type, mrr_mode, join_tab->table->file); } -void JOIN_CACHE_BKAH::save_qpf(struct st_qpf_bka_type *qpf) +void JOIN_CACHE_BKAH::save_explain_data(struct st_explain_bka_type *qpf) { - JOIN_CACHE::save_qpf(qpf); + JOIN_CACHE::save_explain_data(qpf); add_mrr_explain_info(&qpf->mrr_type, mrr_mode, join_tab->table->file); } diff --git a/sql/sql_join_cache.h b/sql/sql_join_cache.h index 75589c3395f..0b03f2b8bab 100644 --- a/sql/sql_join_cache.h +++ b/sql/sql_join_cache.h @@ -63,7 +63,7 @@ typedef struct st_cache_field { class JOIN_TAB_SCAN; -struct st_qpf_bka_type; +struct st_explain_bka_type; /* JOIN_CACHE is the base class to support the implementations of @@ -658,7 +658,7 @@ public: enum_nested_loop_state join_records(bool skip_last); /* Add a comment on the join algorithm employed by the join cache */ - virtual void save_qpf(struct st_qpf_bka_type *qpf); + virtual void save_explain_data(struct st_explain_bka_type *qpf); THD *thd(); @@ -1336,7 +1336,7 @@ public: /* Check index condition of the joined table for a record from BKA cache */ bool skip_index_tuple(range_id_t range_info); - void save_qpf(struct st_qpf_bka_type *qpf); + void save_explain_data(struct st_explain_bka_type *qpf); }; @@ -1427,5 +1427,5 @@ public: /* Check index condition of the joined table for a record from BKAH cache */ bool skip_index_tuple(range_id_t range_info); - void save_qpf(struct st_qpf_bka_type *qpf); + void save_explain_data(struct st_explain_bka_type *qpf); }; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ff71bf4eb09..48c65e68f87 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -448,7 +448,7 @@ void lex_start(THD *thd) lex->thd= lex->unit.thd= thd; - lex->query_plan_footprint= NULL; + lex->explain= NULL; lex->context_stack.empty(); lex->unit.init_query(); @@ -2572,7 +2572,7 @@ void Query_tables_list::destroy_query_tables_list() */ LEX::LEX() - : query_plan_footprint(NULL), + : explain(NULL), result(0), option_type(OPT_DEFAULT), is_lex_started(0), limit_rows_examined_cnt(ULONGLONG_MAX) { @@ -3515,18 +3515,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)) + + Explain_query *qpf; + if ((qpf= inner_join->thd->lex->explain)) { - QPF_select *qp_sel; + Explain_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) { /* @@ -4215,9 +4215,9 @@ int LEX::print_explain(select_result_sink *output, uint8 explain_flags, bool *printed_anything) { int res; - if (query_plan_footprint && query_plan_footprint->have_query_plan()) + if (explain && explain->have_query_plan()) { - res= query_plan_footprint->print_explain(output, explain_flags); + res= explain->print_explain(output, explain_flags); *printed_anything= true; } else @@ -4230,10 +4230,10 @@ int LEX::print_explain(select_result_sink *output, uint8 explain_flags, /* - Save query plan of a UNION. The only variable member is whether the union has - "Using filesort". + Save explain structures 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 + There is also save_union_explain_part2() function, which is called before we read UNION's output. The reason for it is examples like this: @@ -4245,10 +4245,10 @@ int LEX::print_explain(select_result_sink *output, uint8 explain_flags, stage in execution. */ -int st_select_lex_unit::save_union_qpf(QPF_query *output) +int st_select_lex_unit::save_union_explain(Explain_query *output) { SELECT_LEX *first= first_select(); - QPF_union *qpfu= new (output->mem_root) QPF_union; + Explain_union *eu= new (output->mem_root) Explain_union; /* TODO: The following code should be eliminated. If we have a capability to @@ -4264,30 +4264,34 @@ int st_select_lex_unit::save_union_qpf(QPF_query *output) const char *msg="Query plan already deleted"; first->set_explain_type(TRUE/* on_the_fly */); - QPF_select *qp_sel= new (output->mem_root)QPF_select; + Explain_select *qp_sel= new (output->mem_root)Explain_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); + eu->add_select(qp_sel->select_id); return 0; } for (SELECT_LEX *sl= first; sl; sl= sl->next_select()) - qpfu->add_select(sl->select_number); + eu->add_select(sl->select_number); // Save the UNION node - output->add_node(qpfu); + output->add_node(eu); - qpfu->fake_select_type= "UNION RESULT"; - qpfu->using_filesort= test(global_parameters->order_list.first); + eu->fake_select_type= "UNION RESULT"; + eu->using_filesort= test(global_parameters->order_list.first); return 0; } -int st_select_lex_unit::save_union_qpf_part2(QPF_query *output) +/* + @see st_select_lex_unit::save_union_explain +*/ + +int st_select_lex_unit::save_union_explain_part2(Explain_query *output) { - QPF_union *qpfu= output->get_union(first_select()->select_number); + Explain_union *eu= output->get_union(first_select()->select_number); if (fake_select_lex) { for (SELECT_LEX_UNIT *unit= fake_select_lex->first_inner_unit(); @@ -4295,7 +4299,7 @@ int st_select_lex_unit::save_union_qpf_part2(QPF_query *output) { if (!(unit->item && unit->item->eliminated)) { - qpfu->add_child(unit->first_select()->select_number); + eu->add_child(unit->first_select()->select_number); } } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 13140063bff..8bff5c640df 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -618,11 +618,11 @@ class select_result; class JOIN; class select_union; class Procedure; -class QPF_query; +class Explain_query; -void delete_qpf_query(LEX *lex); -void create_qpf_query(LEX *lex, MEM_ROOT *mem_root); -bool print_qpf_query(LEX *lex, THD *thd, String *str); +void delete_explain_query(LEX *lex); +void create_explain_query(LEX *lex, MEM_ROOT *mem_root); +bool print_explain_query(LEX *lex, THD *thd, String *str); class st_select_lex_unit: public st_select_lex_node { protected: @@ -734,8 +734,8 @@ public: List<Item> *get_unit_column_types(); - int save_union_qpf(QPF_query *output); - int save_union_qpf_part2(QPF_query *output); + int save_union_explain(Explain_query *output); + int save_union_explain_part2(Explain_query *output); }; typedef class st_select_lex_unit SELECT_LEX_UNIT; @@ -2368,7 +2368,7 @@ protected: class Delete_plan; class SQL_SELECT; -class QPF_query; +class Explain_query; class QPF_update; /* @@ -2398,8 +2398,8 @@ public: /* Set this plan to be a plan to do nothing because of impossible WHRE*/ void set_impossible_where() { impossible_where= true; } - void save_qpf(QPF_query *query); - void save_qpf_intern(QPF_query *query, QPF_update *qpf); + void save_explain_data(Explain_query *query); + void save_explain_data_intern(Explain_query *query, QPF_update *qpf); virtual ~Update_plan() {} Update_plan() : impossible_where(false), using_filesort(false) {} @@ -2423,7 +2423,7 @@ public: table_rows= rows_arg; } - void save_qpf(QPF_query *query); + void save_explain_data(Explain_query *query); }; @@ -2439,7 +2439,7 @@ struct LEX: public Query_tables_list SELECT_LEX *all_selects_list; /* Query Plan Footprint of a currently running select */ - QPF_query *query_plan_footprint; + Explain_query *explain; char *length,*dec,*change; LEX_STRING name; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 71d68c6730d..76c26da5839 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -598,7 +598,7 @@ static void handle_bootstrap_impl(THD *thd) #if defined(ENABLED_PROFILING) thd->profiling.finish_current_query(); #endif - delete_qpf_query(thd->lex); + delete_explain_query(thd->lex); if (bootstrap_error) break; @@ -1526,7 +1526,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* @note - This function must call delete_qpf_query(). + This function must call delete_explain_query(). */ void log_slow_statement(THD *thd) { @@ -1547,7 +1547,7 @@ void log_slow_statement(THD *thd) (thd->variables.log_slow_filter && !(thd->variables.log_slow_filter & thd->query_plan_flags))) { - delete_qpf_query(thd->lex); + delete_explain_query(thd->lex); DBUG_VOID_RETURN; } @@ -1573,7 +1573,7 @@ void log_slow_statement(THD *thd) thd_proc_info(thd, 0); } - delete_qpf_query(thd->lex); + delete_explain_query(thd->lex); DBUG_VOID_RETURN; } @@ -2201,7 +2201,7 @@ mysql_execute_command(THD *thd) thd->mdl_context.release_transactional_locks(); } - create_qpf_query(thd->lex, thd->mem_root); + create_explain_query(thd->lex, thd->mem_root); #ifndef DBUG_OFF if (lex->sql_command != SQLCOM_SET_OPTION) @@ -3252,7 +3252,7 @@ end_with_restore_list: select_result *result= new select_send(); LEX *lex= thd->lex; if (thd->send_explain_fields(result) || - lex->query_plan_footprint->print_explain(result, lex->describe) || + lex->explain->print_explain(result, lex->describe) || result->send_eof()) res= 1; } @@ -3361,7 +3361,7 @@ end_with_restore_list: select_result *result= new select_send(); LEX *lex= thd->lex; if (thd->send_explain_fields(result) || - lex->query_plan_footprint->print_explain(result, lex->describe) || + lex->explain->print_explain(result, lex->describe) || result->send_eof()) res= 1; } @@ -4901,8 +4901,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) top-level LIMIT */ result->reset_offset_limit(); - thd->lex->query_plan_footprint->print_explain(result, - thd->lex->describe); + thd->lex->explain->print_explain(result, thd->lex->describe); if (lex->describe & DESCRIBE_EXTENDED) { char buff[1024]; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index e3d6c75453e..4a8f3314c8b 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2491,7 +2491,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) object and because of this can be used in different threads. */ lex->thd= thd; - DBUG_ASSERT(!lex->query_plan_footprint); + DBUG_ASSERT(!lex->explain); if (lex->empty_field_list_on_rset) { @@ -3931,8 +3931,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) if (! cursor) cleanup_stmt(); - //psergey: TODO the "EXECUTE problem" is here - delete_qpf_query(thd->lex); + + delete_explain_query(thd->lex); thd->set_statement(&stmt_backup); thd->stmt_arena= old_stmt_arena; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index baaef14e7b9..e7557b92ea4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2305,9 +2305,8 @@ void join_save_qpf(JOIN *join) join->have_query_plan != JOIN::QEP_NOT_PRESENT_YET && join->have_query_plan != JOIN::QEP_DELETED && // this happens when there was no QEP ever, but then //cleanup() is called multiple times - - thd->lex->query_plan_footprint && // for "SET" command in SPs. - !thd->lex->query_plan_footprint->get_select(join->select_lex->select_number)) + thd->lex->explain && // for "SET" command in SPs. + !thd->lex->explain->get_select(join->select_lex->select_number)) { const char *message= NULL; @@ -2317,12 +2316,12 @@ void join_save_qpf(JOIN *join) message= join->zero_result_cause ? join->zero_result_cause : "No tables used"; } - join->save_qpf(thd->lex->query_plan_footprint, - 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 - message); // message + join->save_explain_data(thd->lex->explain, + join->need_tmp, + !join->skip_sort_order && !join->no_order && + (join->order || join->group_list), + join->select_distinct, + message); } } @@ -2347,34 +2346,29 @@ void JOIN::exec() exec_inner(); - if (!exec_qpf_saved) + if (!exec_saved_explain) { if (select_lex->select_number != UINT_MAX && select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ && have_query_plan != QEP_NOT_PRESENT_YET && have_query_plan != QEP_DELETED && // this happens when there was no QEP ever, but then //cleanup() is called multiple times - - thd->lex->query_plan_footprint //&& // for "SET" command in SPs. - /*!thd->lex->query_plan_footprint->get_select(select_lex->select_number)*/) + thd->lex->explain)// for "SET" command in SPs. { const char *message= NULL; - if (!table_count || !tables_list || zero_result_cause) { /* It's a degenerate join */ message= zero_result_cause ? zero_result_cause : "No tables used"; } - save_qpf(thd->lex->query_plan_footprint, - need_tmp, // need_tmp_table - // !skip_sort_order && !no_order && - // (order || group_list), // bool need_order - order != 0 && !skip_sort_order, - select_distinct, // bool distinct - message); // message + save_explain_data(thd->lex->explain, + need_tmp, + order != 0 && !skip_sort_order, + select_distinct, + message); } - exec_qpf_saved= true; + exec_saved_explain= true; } DBUG_EXECUTE_IF("show_explain_probe_join_exec_end", @@ -11170,37 +11164,7 @@ void JOIN::cleanup(bool full) DBUG_PRINT("enter", ("full %u", (uint) full)); if (full) - { - /* Save it again */ -#if 0 - psergey-todo: remove? - if (select_lex->select_number != UINT_MAX && - select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ && - have_query_plan != QEP_NOT_PRESENT_YET && - have_query_plan != QEP_DELETED && // this happens when there was no QEP ever, but then - //cleanup() is called multiple times - - thd->lex->query_plan_footprint //&& // for "SET" command in SPs. - /*!thd->lex->query_plan_footprint->get_select(select_lex->select_number)*/) - { - const char *message= NULL; - - if (!table_count || !tables_list || zero_result_cause) - { - /* It's a degenerate join */ - message= zero_result_cause ? zero_result_cause : "No tables used"; - } - - save_qpf(thd->lex->query_plan_footprint, - need_tmp, // need_tmp_table - !skip_sort_order && !no_order && - (order || group_list), // bool need_order - select_distinct, // bool distinct - message); // message - } -#endif - have_query_plan= QEP_DELETED; //psergey: this is a problem! - } + have_query_plan= QEP_DELETED; if (table) { @@ -22522,16 +22486,17 @@ void append_possible_keys(String *str, TABLE *table, key_map possible_keys) Currently, this function may be called multiple times */ -int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, - bool distinct, const char *message) +int JOIN::save_explain_data(Explain_query *output, bool need_tmp_table, + bool need_order, bool distinct, + const char *message) { - QPF_node *qp_node; + Explain_node *qp_node; JOIN *join= this; /* Legacy: this code used to be a non-member function */ THD *thd=join->thd; const CHARSET_INFO *cs= system_charset_info; int quick_type; int error= 0; - DBUG_ENTER("JOIN::save_qpf"); + DBUG_ENTER("JOIN::save_explain_data"); DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s", (ulong)join->select_lex, join->select_lex->type, message ? message : "NULL")); @@ -22540,8 +22505,8 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, if (message) { - QPF_select *qp_sel; - qp_node= qp_sel= new (output->mem_root) QPF_select; + Explain_select *qp_sel; + qp_node= qp_sel= new (output->mem_root) Explain_select; join->select_lex->set_explain_type(true); qp_sel->select_id= join->select_lex->select_number; @@ -22552,13 +22517,13 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, } else if (join->select_lex == join->unit->fake_select_lex) { - /* Do nothing, QPF_union will create and print fake_select_lex */ + /* Do nothing, Explain_union will create and print fake_select_lex */ } else if (!join->select_lex->master_unit()->derived || join->select_lex->master_unit()->derived->is_materialized_derived()) { - QPF_select *qp_sel; - qp_node= qp_sel= new (output->mem_root) QPF_select; + Explain_select *qp_sel; + qp_node= qp_sel= new (output->mem_root) Explain_select; table_map used_tables=0; join->select_lex->set_explain_type(true); @@ -22606,7 +22571,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, tab= pre_sort_join_tab; } - QPF_table_access *qpt= new (output->mem_root) QPF_table_access; + Explain_table_access *qpt= new (output->mem_root) Explain_table_access; qp_sel->add_table(qpt); qpt->key.set(thd->mem_root, NULL, (uint)-1); qpt->quick_info= NULL; @@ -22701,7 +22666,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, */ if (tab->select && tab->select->quick && tab_type != JT_CONST) { - qpt->quick_info= new QPF_quick_select; + qpt->quick_info= new Explain_quick_select; tab->select->quick->save_info(thd->mem_root, qpt->quick_info); } @@ -22981,7 +22946,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, if (tab->cache) { qpt->push_extra(ET_USING_JOIN_BUFFER); - tab->cache->save_qpf(&qpt->bka_type); + tab->cache->save_explain_data(&qpt->bka_type); } } @@ -23039,9 +23004,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, DBUG_ENTER("select_describe"); /* Update the QPF with latest values of using_temporary, using_filesort */ - QPF_select *qp; + Explain_select *qp; uint select_nr= join->select_lex->select_number; - if ((qp= thd->lex->query_plan_footprint->get_select(select_nr))) + if ((qp= thd->lex->explain->get_select(select_nr))) { qp->using_temporary= need_tmp_table; qp->using_filesort= need_order; @@ -23095,7 +23060,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) if (unit->is_union()) { - unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization + unit->fake_select_lex->select_number= FAKE_SELECT_LEX_ID; // jost for initialization unit->fake_select_lex->type= "UNION RESULT"; unit->fake_select_lex->options|= SELECT_DESCRIBE; if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE))) diff --git a/sql/sql_select.h b/sql/sql_select.h index b3177333d12..fc2ffb3c175 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -258,7 +258,7 @@ typedef struct st_join_table { JOIN_TAB_RANGE *bush_children; /* Special content for EXPLAIN 'Extra' column or NULL if none */ - enum Extra_tag info; + enum explain_extra_tag info; /* Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra' @@ -1336,7 +1336,7 @@ public: emb_sjm_nest= NULL; sjm_lookup_tables= 0; - exec_qpf_saved= false; + exec_saved_explain= false; /* The following is needed because JOIN::cleanup(true) may be called for joins for which JOIN::optimize was aborted with an error before a proper @@ -1344,7 +1344,13 @@ public: */ table_access_tabs= NULL; } - bool exec_qpf_saved; + + /* + TRUE <=> There was a JOIN::exec() call, which saved this JOIN's EXPLAIN. + The idea is that we also save at the end of JOIN::optimize(), but that + might not be the final plan. + */ + bool exec_saved_explain; int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, COND *conds, uint og_num, ORDER *order, ORDER *group, @@ -1470,8 +1476,8 @@ public: { return (unit->item && unit->item->is_in_predicate()); } - int save_qpf(QPF_query *output, bool need_tmp_table, bool need_order, - bool distinct, const char *message); + int save_explain_data(Explain_query *output, bool need_tmp_table, + bool need_order, bool distinct, const char *message); private: /** TRUE if the query contains an aggregate function but has no GROUP diff --git a/sql/sql_union.cc b/sql/sql_union.cc index a6e935f5cfd..72ba3853110 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -630,8 +630,8 @@ bool st_select_lex_unit::exec() saved_error= optimize(); - if (!was_executed && thd->lex->query_plan_footprint) - save_union_qpf(thd->lex->query_plan_footprint); + if (!was_executed && thd->lex->explain) + save_union_explain(thd->lex->explain); if (uncacheable || !item || !item->assigned() || describe) { @@ -780,8 +780,8 @@ bool st_select_lex_unit::exec() if (!fake_select_lex->ref_pointer_array) fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items; - if (!was_executed && thd->lex->query_plan_footprint) - save_union_qpf_part2(thd->lex->query_plan_footprint); + if (!was_executed && thd->lex->explain) + save_union_explain_part2(thd->lex->explain); saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array, &result_table_list, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 2881f6a7a1d..cf6cc46e11c 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -500,7 +500,7 @@ int mysql_update(THD *thd, if (thd->lex->describe) goto exit_without_my_ok; - query_plan.save_qpf(thd->lex->query_plan_footprint); + query_plan.save_explain_data(thd->lex->explain); thd->apc_target.enable(); apc_target_enabled= true; DBUG_EXECUTE_IF("show_explain_probe_update_exec_start", @@ -1031,7 +1031,7 @@ err: exit_without_my_ok: DBUG_ASSERT(!apc_target_enabled); - query_plan.save_qpf(thd->lex->query_plan_footprint); + query_plan.save_explain_data(thd->lex->explain); select_send *result; if (!(result= new select_send())) @@ -1039,7 +1039,7 @@ exit_without_my_ok: List<Item> dummy; /* note: looked in 5.6 and they too use a dummy list like this */ result->prepare(dummy, &thd->lex->unit); thd->send_explain_fields(result); - int err2= thd->lex->query_plan_footprint->print_explain(result, + int err2= thd->lex->explain->print_explain(result, thd->lex->describe); if (err2) result->abort_result_set(); @@ -1518,7 +1518,7 @@ bool mysql_multi_update(THD *thd, { if (explain) { - thd->lex->query_plan_footprint->print_explain(output, thd->lex->describe); + thd->lex->explain->print_explain(output, thd->lex->describe); output->send_eof(); delete output; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d5aee86fea3..d1ac0fec34a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1661,6 +1661,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); definer_opt no_definer definer parse_vcol_expr vcol_opt_specifier vcol_opt_attribute vcol_opt_attribute_list vcol_attribute + explainable_command END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt @@ -12029,14 +12030,14 @@ describe: } | describe_command opt_extended_describe { Lex->describe|= DESCRIBE_NORMAL; } - explanable_command + explainable_command { LEX *lex=Lex; lex->select_lex.options|= SELECT_DESCRIBE; } ; -explanable_command: +explainable_command: select | insert | replace |