diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2014-11-28 02:36:31 +0300 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2014-11-28 02:36:31 +0300 |
commit | d5fbfb9a93704ebe4b1df37f74850a7464140991 (patch) | |
tree | bdb7b297fd87a9c55d294f7da7271fcc77245bd3 | |
parent | 461dbd80d2ea96034f330dd238282d2167ed2c4d (diff) | |
download | mariadb-git-d5fbfb9a93704ebe4b1df37f74850a7464140991.tar.gz |
EXPLAIN FORMAT=JSON: Add support for single-table UPDATE/DELETE.
-rw-r--r-- | mysql-test/r/explain_json.result | 59 | ||||
-rw-r--r-- | mysql-test/t/explain_json.test | 10 | ||||
-rw-r--r-- | sql/sql_delete.cc | 26 | ||||
-rw-r--r-- | sql/sql_explain.cc | 313 | ||||
-rw-r--r-- | sql/sql_explain.h | 35 | ||||
-rw-r--r-- | sql/sql_lex.h | 7 | ||||
-rw-r--r-- | sql/sql_select.cc | 132 | ||||
-rw-r--r-- | sql/sql_select.h | 20 | ||||
-rw-r--r-- | sql/sql_update.cc | 4 |
9 files changed, 409 insertions, 197 deletions
diff --git a/mysql-test/r/explain_json.result b/mysql-test/r/explain_json.result index ec775c8d618..fff80d976b9 100644 --- a/mysql-test/r/explain_json.result +++ b/mysql-test/r/explain_json.result @@ -199,7 +199,7 @@ EXPLAIN }, { "query_block": { - "select_id": 1, + "select_id": 2, "table": { "table_name": "B", "access_type": "ALL", @@ -233,7 +233,7 @@ EXPLAIN }, { "query_block": { - "select_id": 1, + "select_id": 2, "table": { "table_name": "B", "access_type": "ALL", @@ -265,7 +265,7 @@ EXPLAIN "subqueries": [ { "query_block": { - "select_id": 1, + "select_id": 2, "table": { "table_name": "t1", "access_type": "ALL", @@ -295,7 +295,7 @@ EXPLAIN "subqueries": [ { "query_block": { - "select_id": 1, + "select_id": 2, "table": { "table_name": "t1", "access_type": "ALL", @@ -342,4 +342,55 @@ EXPLAIN } } drop table t1; +# +# Single-table UPDATE/DELETE +# +explain format=json delete from t0; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "message": "Deleting all rows" + } + } +} +explain format=json delete from t0 where 1 > 2; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "message": "Impossible WHERE" + } + } +} +explain format=json delete from t0 where a < 3; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "delete": 1, + "table_name": "t0", + "access_type": "ALL", + "rows": 10, + "attached_condition": "(t0.a < 3)" + } + } +} +explain format=json update t0 set a=3 where a in (2,3,4); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "update": 1, + "table_name": "t0", + "access_type": "ALL", + "rows": 10, + "attached_condition": "(t0.a in (2,3,4))" + } + } +} drop table t0; diff --git a/mysql-test/t/explain_json.test b/mysql-test/t/explain_json.test index 6dc54f1492b..6a58796ab13 100644 --- a/mysql-test/t/explain_json.test +++ b/mysql-test/t/explain_json.test @@ -70,5 +70,15 @@ select * from t1 A, t1 B where A.a=B.a and A.b < 3 and B.b < 5; drop table t1; +--echo # +--echo # Single-table UPDATE/DELETE +--echo # +explain format=json delete from t0; +explain format=json delete from t0 where 1 > 2; + +explain format=json delete from t0 where a < 3; + +explain format=json update t0 set a=3 where a in (2,3,4); + drop table t0; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index da2f7b156fe..a4d88b5ee5d 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_explain_data(Explain_query *query) +void Delete_plan::save_explain_data(MEM_ROOT *mem_root, Explain_query *query) { Explain_delete* explain= new Explain_delete; @@ -64,22 +64,23 @@ void Delete_plan::save_explain_data(Explain_query *query) else { explain->deleting_all_rows= false; - Update_plan::save_explain_data_intern(query, explain); + Update_plan::save_explain_data_intern(mem_root, query, explain); } query->add_upd_del_plan(explain); } -void Update_plan::save_explain_data(Explain_query *query) +void Update_plan::save_explain_data(MEM_ROOT *mem_root, Explain_query *query) { Explain_update* explain= new Explain_update; - save_explain_data_intern(query, explain); + save_explain_data_intern(mem_root, query, explain); query->add_upd_del_plan(explain); } -void Update_plan::save_explain_data_intern(Explain_query *query, +void Update_plan::save_explain_data_intern(MEM_ROOT *mem_root, + Explain_query *query, Explain_update *explain) { explain->select_type= "SIMPLE"; @@ -141,10 +142,12 @@ void Update_plan::save_explain_data_intern(Explain_query *query, } explain->using_where= MY_TEST(select && select->cond); + explain->where_cond= select? select->cond: NULL; explain->using_filesort= using_filesort; explain->using_io_buffer= using_io_buffer; - make_possible_keys_line(table, possible_keys, &explain->possible_keys_line); + append_possible_keys(mem_root, explain->possible_keys, table, + possible_keys); explain->quick_info= NULL; @@ -157,11 +160,8 @@ void Update_plan::save_explain_data_intern(Explain_query *query, { if (index != MAX_KEY) { - explain->key_str.append(table->key_info[index].name); - char buf[64]; - size_t length; - length= longlong10_to_str(table->key_info[index].key_length, buf, 10) - buf; - explain->key_len_str.append(buf, length); + explain->key.set(mem_root, &table->key_info[index], + table->key_info[index].key_length); } } explain->rows= scanned_rows; @@ -460,7 +460,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (thd->lex->describe) goto produce_explain_and_leave; - query_plan.save_explain_data(thd->lex->explain); + query_plan.save_explain_data(thd->mem_root, thd->lex->explain); DBUG_EXECUTE_IF("show_explain_probe_delete_exec_start", dbug_serve_apcs(thd, 1);); @@ -698,7 +698,7 @@ produce_explain_and_leave: We come here for various "degenerate" query plans: impossible WHERE, no-partitions-used, impossible-range, etc. */ - query_plan.save_explain_data(thd->lex->explain); + query_plan.save_explain_data(thd->mem_root, thd->lex->explain); send_nothing_and_leave: /* diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index a37d324180f..f8a45b55195 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -22,6 +22,10 @@ #include "sql_select.h" #include "my_json_writer.h" +const char * STR_DELETING_ALL_ROWS= "Deleting all rows"; +const char * STR_IMPOSSIBLE_WHERE= "Impossible WHERE"; +const char * STR_NO_ROWS_AFTER_PRUNING= "No matching rows after partition pruning"; + Explain_query::Explain_query(THD *thd_arg) : upd_del_plan(NULL), insert_plan(NULL), thd(thd_arg), apc_enabled(false) { @@ -188,10 +192,7 @@ void Explain_query::print_explain_json(select_result_sink *output, bool is_analy writer.start_object(); if (upd_del_plan) - { - //upd_del_plan->print_explain(this, output, explain_flags, is_analyze); - DBUG_ASSERT(0); - } + upd_del_plan->print_explain_json(this, &writer, is_analyze); else if (insert_plan) { //insert_plan->print_explain(this, output, explain_flags, is_analyze); @@ -270,6 +271,120 @@ static void push_string_list(List<Item> *item_list, String_list &lines, } +/* + Print an EXPLAIN output row, based on information provided in the parameters + + @note + Parameters that may have NULL value in EXPLAIN output, should be passed + (char*)NULL. + + @return + 0 - OK + 1 - OOM Error +*/ + +static +int print_explain_row(select_result_sink *result, + uint8 options, bool is_analyze, + uint select_number, + const char *select_type, + const char *table_name, + const char *partitions, + enum join_type jtype, + String_list *possible_keys, + const char *index, + const char *key_len, + const char *ref, + ha_rows *rows, + ha_rows *r_rows, + double r_filtered, + const char *extra) +{ + Item *item_null= new Item_null(); + List<Item> item_list; + Item *item; + + item_list.push_back(new Item_int((int32) select_number)); + item_list.push_back(new Item_string_sys(select_type)); + item_list.push_back(new Item_string_sys(table_name)); + if (options & DESCRIBE_PARTITIONS) + { + if (partitions) + { + item_list.push_back(new Item_string_sys(partitions)); + } + else + item_list.push_back(item_null); + } + + const char *jtype_str= join_type_str[jtype]; + item_list.push_back(new Item_string_sys(jtype_str)); + + /* 'possible_keys' */ + if (possible_keys && !possible_keys->is_empty()) + { + StringBuffer<64> possible_keys_buf; + push_string_list(&item_list, *possible_keys, &possible_keys_buf); + } + else + item_list.push_back(item_null); + + /* 'index */ + item= index ? new Item_string_sys(index) : item_null; + item_list.push_back(item); + + /* 'key_len */ + item= key_len ? new Item_string_sys(key_len) : item_null; + item_list.push_back(item); + + /* 'ref' */ + item= ref ? new Item_string_sys(ref) : item_null; + item_list.push_back(item); + + /* 'rows' */ + if (rows) + { + item_list.push_back(new Item_int(*rows, + MY_INT64_NUM_DECIMAL_DIGITS)); + } + else + item_list.push_back(item_null); + + /* 'r_rows' */ + if (is_analyze) + { + if (r_rows) + { + item_list.push_back(new Item_int(*r_rows, + MY_INT64_NUM_DECIMAL_DIGITS)); + } + else + item_list.push_back(item_null); + } + + /* 'filtered' */ + const double filtered=100.0; + if (options & DESCRIBE_EXTENDED || is_analyze) + item_list.push_back(new Item_float(filtered, 2)); + + /* 'r_filtered' */ + if (is_analyze) + item_list.push_back(new Item_float(r_filtered, 2)); + + /* 'Extra' */ + if (extra) + item_list.push_back(new Item_string_sys(extra)); + else + item_list.push_back(item_null); + + if (result->send_data(item_list)) + return 1; + return 0; +} + + + + uint Explain_union::make_union_table_name(char *buf) { uint childno= 0; @@ -538,7 +653,7 @@ void Explain_select::print_explain_json(Explain_query *query, Json_writer_nesting_guard guard(writer); writer->add_member("query_block").start_object(); - writer->add_member("select_id").add_ll(1); + writer->add_member("select_id").add_ll(select_id); if (message) { writer->add_member("table").start_object(); @@ -565,7 +680,15 @@ void Explain_table_access::push_extra(enum explain_extra_tag extra_tag) } -void Explain_table_access::fill_key_str(String *key_str, bool is_json) +/* + Put the contents of 'key' field of EXPLAIN otuput into key_str. + + It is surprisingly complex: + - hash join shows #hash#used_key + - quick selects that use single index will print index name +*/ + +void Explain_table_access::fill_key_str(String *key_str, bool is_json) const { const CHARSET_INFO *cs= system_charset_info; bool is_hj= (type == JT_HASH || type == JT_HASH_NEXT || @@ -607,7 +730,7 @@ void Explain_table_access::fill_key_str(String *key_str, bool is_json) the column legacy, it is superceded by used_key_parts. */ -void Explain_table_access::fill_key_len_str(String *key_len_str) +void Explain_table_access::fill_key_len_str(String *key_len_str) const { bool is_hj= (type == JT_HASH || type == JT_HASH_NEXT || type == JT_HASH_RANGE || type == JT_HASH_INDEX_MERGE); @@ -996,9 +1119,6 @@ void Explain_table_access::print_explain_json(Json_writer *writer, writer->end_object(); } - - // TODO: here, if quick select is not basic, print its nested form. - /* `ref` */ if (!ref_list.is_empty()) { @@ -1320,7 +1440,7 @@ int Explain_delete::print_explain(Explain_query *query, { if (deleting_all_rows) { - const char *msg= "Deleting all rows"; + const char *msg= STR_DELETING_ALL_ROWS; int res= print_explain_message_line(output, explain_flags, is_analyze, 1 /*select number*/, select_type, &rows, msg); @@ -1335,6 +1455,27 @@ int Explain_delete::print_explain(Explain_query *query, } +void Explain_delete::print_explain_json(Explain_query *query, + Json_writer *writer, + bool is_analyze) +{ + Json_writer_nesting_guard guard(writer); + + if (deleting_all_rows) + { + writer->add_member("query_block").start_object(); + writer->add_member("select_id").add_ll(1); + writer->add_member("table").start_object(); + // just like mysql-5.6, we don't print table name. Is this ok? + writer->add_member("message").add_str(STR_DELETING_ALL_ROWS); + writer->end_object(); // table + writer->end_object(); // query_block + return; + } + Explain_update::print_explain_json(query, writer, is_analyze); +} + + int Explain_update::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, @@ -1346,8 +1487,8 @@ int Explain_update::print_explain(Explain_query *query, if (impossible_where || no_partitions) { const char *msg= impossible_where ? - "Impossible WHERE" : - "No matching rows after partition pruning"; + STR_IMPOSSIBLE_WHERE : + STR_NO_ROWS_AFTER_PRUNING; int res= print_explain_message_line(output, explain_flags, is_analyze, 1 /*select number*/, select_type, @@ -1356,7 +1497,6 @@ int Explain_update::print_explain(Explain_query *query, return res; } - if (quick_info) { quick_info->print_key(&key_buf); @@ -1370,10 +1510,13 @@ int Explain_update::print_explain(Explain_query *query, extra_str.append(quick_buf); } } - else + else if (key.get_key_name()) { - key_buf.copy(key_str); - key_len_buf.copy(key_len_str); + const char *name= key.get_key_name(); + key_buf.set(name, strlen(name), &my_charset_bin); + char buf[64]; + size_t length= longlong10_to_str(key.get_key_len(), buf, 10) - buf; + key_len_buf.copy(buf, length, &my_charset_bin); } if (using_where) @@ -1417,7 +1560,7 @@ int Explain_update::print_explain(Explain_query *query, table_name.c_ptr(), used_partitions_set? used_partitions.c_ptr() : NULL, jtype, - possible_keys_line.length()? possible_keys_line.c_ptr(): NULL, + &possible_keys, key_buf.length()? key_buf.c_ptr() : NULL, key_len_buf.length() ? key_len_buf.c_ptr() : NULL, NULL, /* 'ref' is always NULL in single-table EXPLAIN DELETE */ @@ -1430,6 +1573,140 @@ int Explain_update::print_explain(Explain_query *query, } +void Explain_update::print_explain_json(Explain_query *query, + Json_writer *writer, + bool is_analyze) +{ + Json_writer_nesting_guard guard(writer); + + writer->add_member("query_block").start_object(); + writer->add_member("select_id").add_ll(1); + + if (impossible_where || no_partitions) + { + const char *msg= impossible_where ? STR_IMPOSSIBLE_WHERE : + STR_NO_ROWS_AFTER_PRUNING; + writer->add_member("table").start_object(); + writer->add_member("message").add_str(msg); + writer->end_object(); // table + writer->end_object(); // query_block + return; + } + + writer->add_member("table").start_object(); + + if (get_type() == EXPLAIN_UPDATE) + writer->add_member("update").add_ll(1); + else + writer->add_member("delete").add_ll(1); + + writer->add_member("table_name").add_str(table_name); + writer->add_member("access_type").add_str(join_type_str[jtype]); + + if (!possible_keys.is_empty()) + { + List_iterator_fast<char> it(possible_keys); + const char *name; + writer->add_member("possible_keys").start_array(); + while ((name= it++)) + writer->add_str(name); + writer->end_array(); + } + + /* `key`, `key_length` */ + if (quick_info && quick_info->is_basic()) + { + StringBuffer<64> key_buf; + StringBuffer<64> key_len_buf; + quick_info->print_extra_recursive(&key_buf); + quick_info->print_key_len(&key_len_buf); + + writer->add_member("key").add_str(key_buf); + writer->add_member("key_length").add_str(key_len_buf); + } + else if (key.get_key_name()) + { + writer->add_member("key").add_str(key.get_key_name()); + writer->add_member("key_length").add_str(key.get_key_len()); + } + + /* `used_key_parts` */ + String_list *parts_list= NULL; + if (quick_info && quick_info->is_basic()) + parts_list= &quick_info->range.key_parts_list; + else + parts_list= &key.key_parts_list; + + if (parts_list && !parts_list->is_empty()) + { + List_iterator_fast<char> it(*parts_list); + const char *name; + writer->add_member("used_key_parts").start_array(); + while ((name= it++)) + writer->add_str(name); + writer->end_array(); + } + + if (quick_info && !quick_info->is_basic()) + { + writer->add_member("index_merge").start_object(); + quick_info->print_json(writer); + writer->end_object(); + } + +#if 0 + /* `ref` */ + if (!ref_list.is_empty()) + { + List_iterator_fast<char> it(ref_list); + const char *str; + writer->add_member("ref").start_array(); + while ((str= it++)) + writer->add_str(str); + writer->end_array(); + } +#endif + + /* `rows` */ + writer->add_member("rows").add_ll(rows); + + /* `r_rows` */ + if (is_analyze && tracker.has_scans()) + { + ha_rows avg_rows= tracker.get_avg_rows(); + writer->add_member("r_rows").add_ll(avg_rows); + } + + /* UPDATE/DELETE do not produce `filtered` estimate */ + + /* `r_filtered` */ + if (is_analyze) + { + double r_filtered= tracker.get_filtered_after_where(); + writer->add_member("r_filtered").add_double(r_filtered); + } + + if (mrr_type.length() != 0) + writer->add_member("mrr_type").add_str(mrr_type.ptr()); + + if (using_filesort) + writer->add_member("using_filesort").add_ll(1); + + if (using_io_buffer) + writer->add_member("using_io_buffer").add_ll(1); + + if (where_cond) + { + writer->add_member("attached_condition"); + write_item(writer, where_cond); + } + + writer->end_object(); // table + print_explain_json_for_children(query, writer, is_analyze); + writer->end_object(); // query_block +} + + int Explain_insert::print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 6cc8e012a95..5fd1d5ec59a 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -432,6 +432,11 @@ class Explain_index_use : public Sql_alloc public: String_list key_parts_list; + Explain_index_use() + { + clear(); + } + void clear() { key_name= NULL; @@ -440,8 +445,8 @@ public: void set(MEM_ROOT *root, KEY *key_name, uint key_len_arg); void set_pseudo_key(MEM_ROOT *root, const char *key_name); - inline const char *get_key_name() { return key_name; } - inline uint get_key_len() { return key_len; } + inline const char *get_key_name() const { return key_name; } + inline uint get_key_len() const { return key_len; } }; @@ -584,8 +589,8 @@ public: private: void append_tag_name(String *str, enum explain_extra_tag tag); - void fill_key_str(String *key_str, bool is_json); - void fill_key_len_str(String *key_len_str); + void fill_key_str(String *key_str, bool is_json) const; + void fill_key_len_str(String *key_len_str) const; double get_r_filtered(); void tag_to_json(Json_writer *writer, enum explain_extra_tag tag); }; @@ -614,14 +619,22 @@ public: StringBuffer<64> table_name; enum join_type jtype; - StringBuffer<128> possible_keys_line; - StringBuffer<128> key_str; - StringBuffer<128> key_len_str; + String_list possible_keys; + + /* Used key when doing a full index scan (possibly with limit) */ + Explain_index_use key; + + /* + MRR that's used with quick select. This should probably belong to the + quick select + */ StringBuffer<64> mrr_type; Explain_quick_select *quick_info; bool using_where; + Item *where_cond; + ha_rows rows; bool using_filesort; @@ -632,8 +645,8 @@ public: virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze); - virtual void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) - { /* EXPLAIN_JSON_NOT_IMPL */} + virtual void print_explain_json(Explain_query *query, Json_writer *writer, + bool is_analyze); }; @@ -678,8 +691,8 @@ public: virtual int print_explain(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze); - virtual void print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze) - { /* EXPLAIN_JSON_NOT_IMPL */} + virtual void print_explain_json(Explain_query *query, Json_writer *writer, + bool is_analyze); }; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7910943c4cf..b9546d71306 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2303,8 +2303,9 @@ public: void set_impossible_where() { impossible_where= true; } void set_no_partitions() { no_partitions= true; } - void save_explain_data(Explain_query *query); - void save_explain_data_intern(Explain_query *query, Explain_update *eu); + void save_explain_data(MEM_ROOT *mem_root, Explain_query *query); + void save_explain_data_intern(MEM_ROOT *mem_root, Explain_query *query, + Explain_update *eu); virtual ~Update_plan() {} @@ -2335,7 +2336,7 @@ public: scanned_rows= rows_arg; } - void save_explain_data(Explain_query *query); + void save_explain_data(MEM_ROOT *mem_root, Explain_query *query); }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 185c0929670..f66525d9f18 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -23126,135 +23126,7 @@ int print_explain_message_line(select_result_sink *result, return 0; } - -/* - Make a comma-separated list of possible_keys names and add it into the string -*/ - -void make_possible_keys_line(TABLE *table, key_map possible_keys, String *line) -{ - if (!possible_keys.is_clear_all()) - { - uint j; - for (j=0 ; j < table->s->keys ; j++) - { - if (possible_keys.is_set(j)) - { - if (line->length()) - line->append(','); - line->append(table->key_info[j].name, - strlen(table->key_info[j].name), - system_charset_info); - } - } - } -} - -/* - Print an EXPLAIN output row, based on information provided in the parameters - - @note - Parameters that may have NULL value in EXPLAIN output, should be passed - (char*)NULL. - - @return - 0 - OK - 1 - OOM Error -*/ - -int print_explain_row(select_result_sink *result, - uint8 options, bool is_analyze, - uint select_number, - const char *select_type, - const char *table_name, - const char *partitions, - enum join_type jtype, - const char *possible_keys, - const char *index, - const char *key_len, - const char *ref, - ha_rows *rows, - ha_rows *r_rows, - double r_filtered, - const char *extra) -{ - Item *item_null= new Item_null(); - List<Item> item_list; - Item *item; - - item_list.push_back(new Item_int((int32) select_number)); - item_list.push_back(new Item_string_sys(select_type)); - item_list.push_back(new Item_string_sys(table_name)); - if (options & DESCRIBE_PARTITIONS) - { - if (partitions) - { - item_list.push_back(new Item_string_sys(partitions)); - } - else - item_list.push_back(item_null); - } - - const char *jtype_str= join_type_str[jtype]; - item_list.push_back(new Item_string_sys(jtype_str)); - - item= possible_keys? new Item_string_sys(possible_keys) : item_null; - item_list.push_back(item); - - /* 'index */ - item= index ? new Item_string_sys(index) : item_null; - item_list.push_back(item); - - /* 'key_len */ - item= key_len ? new Item_string_sys(key_len) : item_null; - item_list.push_back(item); - - /* 'ref' */ - item= ref ? new Item_string_sys(ref) : item_null; - item_list.push_back(item); - - /* 'rows' */ - if (rows) - { - item_list.push_back(new Item_int(*rows, - MY_INT64_NUM_DECIMAL_DIGITS)); - } - else - item_list.push_back(item_null); - - /* 'r_rows' */ - if (is_analyze) - { - if (r_rows) - { - item_list.push_back(new Item_int(*r_rows, - MY_INT64_NUM_DECIMAL_DIGITS)); - } - else - item_list.push_back(item_null); - } - - /* 'filtered' */ - const double filtered=100.0; - if (options & DESCRIBE_EXTENDED || is_analyze) - item_list.push_back(new Item_float(filtered, 2)); - - /* 'r_filtered' */ - if (is_analyze) - item_list.push_back(new Item_float(r_filtered, 2)); - - /* 'Extra' */ - if (extra) - item_list.push_back(new Item_string_sys(extra)); - else - item_list.push_back(item_null); - - if (result->send_data(item_list)) - return 1; - return 0; -} - - +#if 0 int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, SELECT_LEX *select_lex, uint8 explain_flags) { @@ -23327,7 +23199,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, return 1; return 0; } - +#endif /* Append MRR information from quick select to the given string diff --git a/sql/sql_select.h b/sql/sql_select.h index ac1ea05a498..9463005b2ba 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1832,8 +1832,10 @@ inline bool optimizer_flag(THD *thd, uint flag) return (thd->variables.optimizer_switch & flag); } +/* int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, SELECT_LEX *select_lex, uint8 select_options); +*/ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, ha_rows limit, ha_rows *scanned_limit, @@ -1861,22 +1863,8 @@ int print_explain_message_line(select_result_sink *result, ha_rows *rows, const char *message); void explain_append_mrr_info(QUICK_RANGE_SELECT *quick, String *res); -int print_explain_row(select_result_sink *result, - uint8 options, bool is_analyze, - uint select_number, - const char *select_type, - const char *table_name, - const char *partitions, - enum join_type jtype, - const char *possible_keys, - const char *index, - const char *key_len, - const char *ref, - ha_rows *rows, - ha_rows *r_rows, - double r_filtered, - const char *extra); -void make_possible_keys_line(TABLE *table, key_map possible_keys, String *line); +int append_possible_keys(MEM_ROOT *alloc, String_list &list, TABLE *table, + key_map possible_keys); /**************************************************************************** Temporary table support for SQL Runtime diff --git a/sql/sql_update.cc b/sql/sql_update.cc index fa5b6968795..f4086bdee1f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -517,7 +517,7 @@ int mysql_update(THD *thd, */ if (thd->lex->describe) goto produce_explain_and_leave; - query_plan.save_explain_data(thd->lex->explain); + query_plan.save_explain_data(thd->mem_root, thd->lex->explain); DBUG_EXECUTE_IF("show_explain_probe_update_exec_start", dbug_serve_apcs(thd, 1);); @@ -1037,7 +1037,7 @@ produce_explain_and_leave: We come here for various "degenerate" query plans: impossible WHERE, no-partitions-used, impossible-range, etc. */ - query_plan.save_explain_data(thd->lex->explain); + query_plan.save_explain_data(thd->mem_root, thd->lex->explain); emit_explain_and_leave: int err2= thd->lex->explain->send_explain(thd); |