Commit 2ac3b39e authored by Sergei Petrunia's avatar Sergei Petrunia

EXPLAIN FORMAT=JSON: support derived tables

parent 3a5e080d
......@@ -393,4 +393,75 @@ EXPLAIN
}
}
}
#
# A derived table
#
create table t1 (a int, b int);
insert into t1 select a,a from t0;
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl
where cnt>0;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"rows": 10,
"filtered": 100,
"attached_condition": "(tbl.cnt > 0)",
"materialized": {
"query_block": {
"select_id": 2,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl1, t1 as
tbl2 where cnt=tbl2.a;
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "tbl2",
"access_type": "ALL",
"rows": 10,
"filtered": 100,
"attached_condition": "(tbl2.a is not null)"
},
"table": {
"table_name": "<derived2>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"key_length": "8",
"used_key_parts": ["cnt"],
"ref": ["test.tbl2.a"],
"rows": 2,
"filtered": 100,
"attached_condition": "(tbl1.cnt = tbl2.a)",
"materialized": {
"query_block": {
"select_id": 2,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
drop table t0;
......@@ -80,5 +80,18 @@ explain format=json delete from t0 where a < 3;
explain format=json update t0 set a=3 where a in (2,3,4);
--echo #
--echo # A derived table
--echo #
create table t1 (a int, b int);
insert into t1 select a,a from t0;
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl
where cnt>0;
explain format=json
select * from (select a, count(*) as cnt from t1 group by a) as tbl1, t1 as
tbl2 where cnt=tbl2.a;
drop table t0;
......@@ -558,18 +558,29 @@ void Explain_node::print_explain_json_for_children(Explain_query *query,
Json_writer *writer,
bool is_analyze)
{
if (!children.elements())
return;
writer->add_member("subqueries").start_array();
Json_writer_nesting_guard guard(writer);
bool started= false;
for (int i= 0; i < (int) children.elements(); i++)
{
writer->start_object();
Explain_node *node= query->get_node(children.at(i));
/* Derived tables are printed inside Explain_table_access objects */
if (node->is_derived_table)
continue;
if (!started)
{
writer->add_member("subqueries").start_array();
started= true;
}
writer->start_object();
node->print_explain_json(query, writer, is_analyze);
writer->end_object();
}
writer->end_array();
if (started)
writer->end_array();
}
......@@ -665,7 +676,7 @@ void Explain_select::print_explain_json(Explain_query *query,
for (uint i=0; i< n_join_tabs; i++)
{
// psergey-todo: Need to honor SJM nests...
join_tabs[i]->print_explain_json(writer, is_analyze);
join_tabs[i]->print_explain_json(query, writer, is_analyze);
}
}
......@@ -1054,7 +1065,8 @@ void Explain_table_access::tag_to_json(Json_writer *writer, enum explain_extra_t
}
void Explain_table_access::print_explain_json(Json_writer *writer,
void Explain_table_access::print_explain_json(Explain_query *query,
Json_writer *writer,
bool is_analyze)
{
Json_writer_nesting_guard guard(writer);
......@@ -1169,6 +1181,15 @@ void Explain_table_access::print_explain_json(Json_writer *writer,
}
}
if (derived_select_number)
{
/* This is a derived table. Print its contents here */
writer->add_member("materialized").start_object();
Explain_node *node= query->get_node(derived_select_number);
node->print_explain_json(query, writer, is_analyze);
writer->end_object();
}
writer->end_object();
}
......
......@@ -92,9 +92,16 @@ public:
EXPLAIN_INSERT
};
Explain_node() : is_derived_table(false) {}
virtual enum explain_node_type get_type()= 0;
virtual int get_select_id()= 0;
/*
TRUE means this is a derived table. FALSE means otherwise.
*/
bool is_derived_table;
/*
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.
......@@ -494,6 +501,7 @@ class Explain_table_access : public Sql_alloc
{
public:
Explain_table_access() :
derived_select_number(0),
where_cond(NULL),
cache_cond(NULL),
pushed_index_cond(NULL)
......@@ -512,6 +520,12 @@ public:
/* id and 'select_type' are cared-of by the parent Explain_select */
StringBuffer<32> table_name;
/*
Non-zero number means this is a derived table. The number can be used to
find the query plan for the derived table
*/
int derived_select_number;
enum join_type type;
StringBuffer<32> used_partitions;
......@@ -581,7 +595,8 @@ public:
bool is_analyze,
uint select_id, const char *select_type,
bool using_temporary, bool using_filesort);
void print_explain_json(Json_writer *writer, bool is_analyze);
void print_explain_json(Explain_query *query, Json_writer *writer,
bool is_analyze);
/* ANALYZE members*/
Table_access_tracker tracker;
......
......@@ -4268,6 +4268,8 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
{
SELECT_LEX *first= first_select();
Explain_union *eu= new (output->mem_root) Explain_union;
if (derived)
eu->is_derived_table= true;
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
eu->add_select(sl->select_number);
......
......@@ -23654,6 +23654,12 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
tab->cache->save_explain_data(&eta->bka_type);
}
}
/*
In case this is a derived table, here we remember the number of
subselect that used to produce it.
*/
eta->derived_select_number= table->derived_select_number;
}
/*
......@@ -23686,6 +23692,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type;
xpl_sel->message= message;
if (select_lex->master_unit()->derived)
xpl_sel->is_derived_table= true;
/* Setting xpl_sel->message means that all other members are invalid */
output->add_node(xpl_sel);
}
......@@ -23703,6 +23711,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
join->select_lex->set_explain_type(true);
xpl_sel->select_id= join->select_lex->select_number;
xpl_sel->select_type= join->select_lex->type;
if (select_lex->master_unit()->derived)
xpl_sel->is_derived_table= true;
JOIN_TAB* const first_top_tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment