diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2014-08-14 01:12:05 +0400 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2014-08-14 01:12:05 +0400 |
commit | 041e03e251e783d51ca86e53112e3b87bd2da146 (patch) | |
tree | 8df2309ea02720724bff15e5af86903e4bb95dd4 /sql/sql_explain.cc | |
parent | a9d43d70f5d83ac652fd970f5b2b8dfdb77c1136 (diff) | |
download | mariadb-git-041e03e251e783d51ca86e53112e3b87bd2da146.tar.gz |
EXPLAIN FORMAT=JSON: produce used_key_parts, JSON-ish output for index_merge.
Diffstat (limited to 'sql/sql_explain.cc')
-rw-r--r-- | sql/sql_explain.cc | 122 |
1 files changed, 110 insertions, 12 deletions
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index f7fc3b106ce..9571e5a2886 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -541,7 +541,7 @@ void Explain_table_access::push_extra(enum explain_extra_tag extra_tag) } -void Explain_table_access::fill_key_str(String *key_str) +void Explain_table_access::fill_key_str(String *key_str, bool is_json) { const CHARSET_INFO *cs= system_charset_info; bool is_hj= (type == JT_HASH || type == JT_HASH_NEXT || @@ -562,7 +562,10 @@ void Explain_table_access::fill_key_str(String *key_str) if (quick_info) { StringBuffer<64> buf2; - quick_info->print_key(&buf2); + if (is_json) + quick_info->print_extra_recursive(&buf2); + else + quick_info->print_key(&buf2); key_str->append(buf2); } if (type == JT_HASH_NEXT) @@ -570,6 +573,16 @@ void Explain_table_access::fill_key_str(String *key_str) } +/* + Fill "key_length". + - this is just used key length for ref/range + - for index_merge, it is a comma-separated list of lengths. + - for hash join, it is key_len:pseudo_key_len + + The column looks identical in tabular and json forms. In JSON, we consider + the column legacy, it is superceded by used_key_parts. +*/ + void Explain_table_access::fill_key_len_str(String *key_len_str) { bool is_hj= (type == JT_HASH || type == JT_HASH_NEXT || @@ -601,6 +614,35 @@ void Explain_table_access::fill_key_len_str(String *key_len_str) } +void Explain_index_use::set(MEM_ROOT *mem_root, KEY *key, uint key_len_arg) +{ + set_pseudo_key(mem_root, key->name); + key_len= key_len_arg; + uint len= 0; + for (uint i= 0; i < key->usable_key_parts; i++) + { + key_parts_list.append_str(mem_root, key->key_part[i].field->field_name); + len += key->key_part[i].store_length; + if (len >= key_len_arg) + break; + } +} + + +void Explain_index_use::set_pseudo_key(MEM_ROOT *root, const char* key_name_arg) +{ + if (key_name_arg) + { + size_t name_len= strlen(key_name_arg); + if ((key_name= (char*)alloc_root(root, name_len+1))) + memcpy(key_name, key_name_arg, name_len+1); + } + else + key_name= NULL; + key_len= -1; +} + + double Explain_table_access::get_r_filtered() { //psergey-todo: modify this to produce separate filtered% for both parts of @@ -660,7 +702,7 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai /* `key` */ StringBuffer<64> key_str; - fill_key_str(&key_str); + fill_key_str(&key_str, false); if (key_str.length() > 0) push_string(&item_list, &key_str); @@ -861,24 +903,51 @@ void Explain_table_access::print_explain_json(Json_writer *writer, writer->add_str(name); writer->end_array(); } + /* `key` */ - StringBuffer<64> key_str; - fill_key_str(&key_str); - if (key_str.length()) - writer->add_member("key").add_str(key_str); + /* For non-basic quick select, 'key' will not be present */ + if (!quick_info || quick_info->is_basic()) + { + StringBuffer<64> key_str; + fill_key_str(&key_str, true); + if (key_str.length()) + writer->add_member("key").add_str(key_str); + } - /* `used_key_parts` */ - if (key_str.length()) - writer->add_member("used_key_parts").add_str("TODO"); - /* `key_length` */ StringBuffer<64> key_len_str; fill_key_len_str(&key_len_str); if (key_len_str.length()) writer->add_member("key_length").add_str(key_len_str); + + /* `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(); + } + + + // TODO: here, if quick select is not basic, print its nested form. /* `ref` */ - // TODO: need to print this as an array. if (!ref_list.is_empty()) { List_iterator_fast<char> it(ref_list); @@ -1046,6 +1115,35 @@ void Explain_quick_select::print_extra(String *str) print_extra_recursive(str); } +void Explain_quick_select::print_json(Json_writer *writer) +{ + if (is_basic()) + { + writer->add_member("range").start_object(); + + writer->add_member("key").add_str(range.get_key_name()); + + List_iterator_fast<char> it(range.key_parts_list); + const char *name; + writer->add_member("used_key_parts").start_array(); + while ((name= it++)) + writer->add_str(name); + writer->end_array(); + + writer->end_object(); + } + else + { + writer->add_member(get_name_by_type()).start_object(); + + List_iterator_fast<Explain_quick_select> it (children); + Explain_quick_select* child; + while ((child = it++)) + child->print_json(writer); + + writer->end_object(); + } +} void Explain_quick_select::print_extra_recursive(String *str) { |