diff options
Diffstat (limited to 'sql/sql_explain.cc')
-rw-r--r-- | sql/sql_explain.cc | 143 |
1 files changed, 136 insertions, 7 deletions
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 7c3918bfd20..90e9635fe5a 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -36,6 +36,11 @@ const char *unit_operation_text[4]= "UNIT RESULT","UNION RESULT","INTERSECT RESULT","EXCEPT RESULT" }; +const char *pushed_unit_operation_text[4]= +{ + "PUSHED UNIT", "PUSHED UNION", "PUSHED INTERSECT", "PUSHED EXCEPT" +}; + const char *pushed_derived_text= "PUSHED DERIVED"; const char *pushed_select_text= "PUSHED SELECT"; @@ -538,7 +543,22 @@ uint Explain_union::make_union_table_name(char *buf) } -int Explain_union::print_explain(Explain_query *query, +int Explain_union::print_explain(Explain_query *query, + select_result_sink *output, + uint8 explain_flags, bool is_analyze) +{ + if (is_pushed_down_to_engine) + return print_explain_pushed_down(output, explain_flags, is_analyze); + else + return print_explain_regular(query, output, explain_flags, is_analyze); +} + +/* + Prints EXPLAIN plan for a regular UNIT (UNION/EXCEPT/INTERSECT), + i.e. UNIT that has not been pushed down to a storage engine +*/ + +int Explain_union::print_explain_regular(Explain_query *query, select_result_sink *output, uint8 explain_flags, bool is_analyze) @@ -555,6 +575,12 @@ int Explain_union::print_explain(Explain_query *query, } if (!using_tmp) + /* + The union operation may not employ a temporary table, for example, + for UNION ALL, in that case the results of the query are sent directly + to the output. So there is no actual UNION operation and we don't need + to print the line in the EXPLAIN output. + */ return 0; /* Print a line with "UNIT RESULT" */ @@ -566,12 +592,11 @@ int Explain_union::print_explain(Explain_query *query, /* `select_type` column */ push_str(thd, &item_list, fake_select_type); - + /* `table` column: something like "<union1,2>" */ uint len= make_union_table_name(table_name_buffer); - item_list.push_back(new (mem_root) - Item_string_sys(thd, table_name_buffer, len), - mem_root); + item_list.push_back( + new (mem_root) Item_string_sys(thd, table_name_buffer, len), mem_root); /* `partitions` column */ if (explain_flags & DESCRIBE_PARTITIONS) @@ -628,7 +653,6 @@ int Explain_union::print_explain(Explain_query *query, extra_buf.length()), mem_root); - //output->unit.offset_limit_cnt= 0; if (output->send_data(item_list)) return 1; @@ -640,10 +664,90 @@ int Explain_union::print_explain(Explain_query *query, } -void Explain_union::print_explain_json(Explain_query *query, +/* + Prints EXPLAIN plan for a UNIT (UNION/EXCEPT/INTERSECT) that + has been pushed down to a storage engine +*/ + +int Explain_union::print_explain_pushed_down(select_result_sink *output, + uint8 explain_flags, + bool is_analyze) +{ + THD *thd= output->thd; + MEM_ROOT *mem_root= thd->mem_root; + List<Item> item_list; + Item *item_null= new (mem_root) Item_null(thd); + + /* `id` column */ + item_list.push_back(item_null, mem_root); + + /* `select_type` column */ + push_str(thd, &item_list, fake_select_type); + + /* `table` column */ + item_list.push_back(item_null, mem_root); + + /* `partitions` column */ + if (explain_flags & DESCRIBE_PARTITIONS) + item_list.push_back(item_null, mem_root); + + /* `type` column */ + item_list.push_back(item_null, mem_root); + + /* `possible_keys` column */ + item_list.push_back(item_null, mem_root); + + /* `key` */ + item_list.push_back(item_null, mem_root); + + /* `key_len` */ + item_list.push_back(item_null, mem_root); + + /* `ref` */ + item_list.push_back(item_null, mem_root); + + /* `rows` */ + item_list.push_back(item_null, mem_root); + + /* `r_rows` */ + if (is_analyze) + item_list.push_back(item_null, mem_root); + + /* `filtered` */ + if (explain_flags & DESCRIBE_EXTENDED || is_analyze) + item_list.push_back(item_null, mem_root); + + /* `r_filtered` */ + if (is_analyze) + item_list.push_back(item_null, mem_root); + + /* `Extra` */ + item_list.push_back(item_null, mem_root); + + if (output->send_data(item_list)) + return 1; + return 0; +} + + +void Explain_union::print_explain_json(Explain_query *query, Json_writer *writer, bool is_analyze, bool no_tmp_tbl) { + if (is_pushed_down_to_engine) + print_explain_json_pushed_down(query, writer, is_analyze, no_tmp_tbl); + else + print_explain_json_regular(query, writer, is_analyze, no_tmp_tbl); +} + +/* + Prints EXPLAIN plan in JSON format for a regular UNIT (UNION/EXCEPT/INTERSECT), + i.e. UNIT that has not been pushed down to a storage engine +*/ + +void Explain_union::print_explain_json_regular( + Explain_query *query, Json_writer *writer, bool is_analyze, bool no_tmp_tbl) +{ Json_writer_nesting_guard guard(writer); char table_name_buffer[SAFE_NAME_LEN]; @@ -701,6 +805,31 @@ void Explain_union::print_explain_json(Explain_query *query, writer->end_object(); } +/* + Prints EXPLAIN plan in JSON format for a UNIT (UNION/EXCEPT/INTERSECT) that + has been pushed down to a storage engine +*/ + +void Explain_union::print_explain_json_pushed_down(Explain_query *query, + Json_writer *writer, + bool is_analyze, + bool no_tmp_tbl) +{ + Json_writer_nesting_guard guard(writer); + + writer->add_member("query_block").start_object(); + + if (is_recursive_cte) + writer->add_member("recursive_union").start_object(); + else + writer->add_member("union_result").start_object(); + + writer->add_member("message").add_str("Pushed union"); + + writer->end_object(); // union_result + writer->end_object(); // query_block +} + /* Print EXPLAINs for all children nodes (i.e. for subqueries) |