summaryrefslogtreecommitdiff
path: root/sql/sql_explain.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_explain.cc')
-rw-r--r--sql/sql_explain.cc143
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)