mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
[SHOW] EXPLAIN UPDATE/DELETE, code reordering
- Add further details, the goal is to pass the testsuite - SJM-nests are not printed correctly yet.
This commit is contained in:
@ -17,6 +17,16 @@ QPF_query::QPF_query()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QPF_query::~QPF_query()
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
for (i=0 ; i < MAX_TABLES; i++)
|
||||||
|
delete unions[i];
|
||||||
|
for (i=0 ; i < MAX_TABLES; i++)
|
||||||
|
delete selects[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QPF_node *QPF_query::get_node(uint select_id)
|
QPF_node *QPF_query::get_node(uint select_id)
|
||||||
{
|
{
|
||||||
if (unions[select_id])
|
if (unions[select_id])
|
||||||
@ -178,6 +188,17 @@ int QPF_union::print_explain(QPF_query *query, select_result_sink *output,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QPF_select::~QPF_select()
|
||||||
|
{
|
||||||
|
if (join_tabs)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i< n_join_tabs; i++)
|
||||||
|
delete join_tabs[i];
|
||||||
|
my_free(join_tabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int QPF_select::print_explain(QPF_query *query, select_result_sink *output,
|
int QPF_select::print_explain(QPF_query *query, select_result_sink *output,
|
||||||
uint8 explain_flags)
|
uint8 explain_flags)
|
||||||
{
|
{
|
||||||
@ -222,6 +243,13 @@ int QPF_select::print_explain(QPF_query *query, select_result_sink *output,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//psergey-TODO: print children here...
|
||||||
|
for (int i= 0; i < (int) children.elements(); i++)
|
||||||
|
{
|
||||||
|
QPF_node *node= query->get_node(children.at(i));
|
||||||
|
node->print_explain(query, output, explain_flags);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +287,10 @@ int QPF_table_access::print_explain(select_result_sink *output, uint8 explain_fl
|
|||||||
|
|
||||||
/* `possible_keys` column */
|
/* `possible_keys` column */
|
||||||
//push_str(item_list, "TODO");
|
//push_str(item_list, "TODO");
|
||||||
item_list.push_back(item_null);
|
if (possible_keys_str.length() > 0)
|
||||||
|
push_string(&item_list, &possible_keys_str);
|
||||||
|
else
|
||||||
|
item_list.push_back(item_null);
|
||||||
|
|
||||||
/* `key` */
|
/* `key` */
|
||||||
if (key_set)
|
if (key_set)
|
||||||
|
@ -48,33 +48,19 @@ class QPF_select : public QPF_node
|
|||||||
public:
|
public:
|
||||||
enum qpf_node_type get_type() { return QPF_SELECT; }
|
enum qpf_node_type get_type() { return QPF_SELECT; }
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Constructs a finished degenerate join plan */
|
|
||||||
QPF_select(int select_id_arg, const char *select_type_arg, const char* msg) :
|
|
||||||
select_id(select_id_arg),
|
|
||||||
select_type(select_type_arg),
|
|
||||||
message(msg),
|
|
||||||
join_tabs(NULL), n_join_tabs(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/* Constructs an un-finished, non degenerate join plan. */
|
|
||||||
QPF_select(int select_id_arg, const char *select_type_arg) :
|
|
||||||
select_id(select_id_arg),
|
|
||||||
select_type(select_type_arg),
|
|
||||||
message(NULL),
|
|
||||||
join_tabs(NULL), n_join_tabs(0)
|
|
||||||
{}
|
|
||||||
#endif
|
|
||||||
QPF_select() :
|
QPF_select() :
|
||||||
message(NULL), join_tabs(NULL),
|
message(NULL), join_tabs(NULL),
|
||||||
using_temporary(false), using_filesort(false)
|
using_temporary(false), using_filesort(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
~QPF_select();
|
||||||
|
|
||||||
bool add_table(QPF_table_access *tab)
|
bool add_table(QPF_table_access *tab)
|
||||||
{
|
{
|
||||||
if (!join_tabs)
|
if (!join_tabs)
|
||||||
{
|
{
|
||||||
join_tabs= (QPF_table_access**) malloc(sizeof(QPF_table_access*) * MAX_TABLES);
|
join_tabs= (QPF_table_access**) my_malloc(sizeof(QPF_table_access*) *
|
||||||
|
MAX_TABLES, MYF(0));
|
||||||
n_join_tabs= 0;
|
n_join_tabs= 0;
|
||||||
}
|
}
|
||||||
join_tabs[n_join_tabs++]= tab;
|
join_tabs[n_join_tabs++]= tab;
|
||||||
@ -104,6 +90,13 @@ public:
|
|||||||
bool using_temporary;
|
bool using_temporary;
|
||||||
bool using_filesort;
|
bool using_filesort;
|
||||||
|
|
||||||
|
/* Child selects. TODO: join this with QPF_union's children? */
|
||||||
|
Dynamic_array<int> children;
|
||||||
|
void add_child(int select_no)
|
||||||
|
{
|
||||||
|
children.append(select_no);
|
||||||
|
}
|
||||||
|
|
||||||
void print_tabular(select_result_sink *output, uint8 explain_flags//,
|
void print_tabular(select_result_sink *output, uint8 explain_flags//,
|
||||||
//bool *printed_anything
|
//bool *printed_anything
|
||||||
);
|
);
|
||||||
@ -143,10 +136,11 @@ public:
|
|||||||
This is the whole query.
|
This is the whole query.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QPF_query
|
class QPF_query : public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QPF_query();
|
QPF_query();
|
||||||
|
~QPF_query();
|
||||||
void add_node(QPF_node *node);
|
void add_node(QPF_node *node);
|
||||||
int print_explain(select_result_sink *output, uint8 explain_flags);
|
int print_explain(select_result_sink *output, uint8 explain_flags);
|
||||||
|
|
||||||
@ -203,7 +197,7 @@ enum Extra_tag
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class QPF_table_access
|
class QPF_table_access : public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void push_extra(enum Extra_tag extra_tag);
|
void push_extra(enum Extra_tag extra_tag);
|
||||||
@ -220,6 +214,7 @@ public:
|
|||||||
bool used_partitions_set;
|
bool used_partitions_set;
|
||||||
|
|
||||||
key_map possible_keys;
|
key_map possible_keys;
|
||||||
|
StringBuffer<256> possible_keys_str;
|
||||||
|
|
||||||
uint key_no;
|
uint key_no;
|
||||||
uint key_length;
|
uint key_length;
|
||||||
|
@ -4814,7 +4814,12 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
|
|||||||
thd->lex->query_plan_footprint= new QPF_query;
|
thd->lex->query_plan_footprint= new QPF_query;
|
||||||
res= mysql_explain_union(thd, &thd->lex->unit, result);
|
res= mysql_explain_union(thd, &thd->lex->unit, result);
|
||||||
|
|
||||||
thd->lex->query_plan_footprint->print_explain(result, thd->lex->describe);
|
if (!res)
|
||||||
|
{
|
||||||
|
thd->lex->query_plan_footprint->print_explain(result, thd->lex->describe);
|
||||||
|
}
|
||||||
|
delete thd->lex->query_plan_footprint;
|
||||||
|
thd->lex->query_plan_footprint= NULL;
|
||||||
|
|
||||||
//psergey-todo: here, produce the EXPLAIN output.
|
//psergey-todo: here, produce the EXPLAIN output.
|
||||||
// mysql_explain_union() itself is only responsible for calling
|
// mysql_explain_union() itself is only responsible for calling
|
||||||
|
@ -22903,6 +22903,21 @@ void QPF_table_access::push_extra(enum Extra_tag extra_tag)
|
|||||||
extra_tags.append(extra_tag);
|
extra_tags.append(extra_tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void append_possible_keys(String *str, TABLE *table, key_map possible_keys)
|
||||||
|
{
|
||||||
|
uint j;
|
||||||
|
for (j=0 ; j < table->s->keys ; j++)
|
||||||
|
{
|
||||||
|
if (possible_keys.is_set(j))
|
||||||
|
{
|
||||||
|
if (str->length())
|
||||||
|
str->append(',');
|
||||||
|
str->append(table->key_info[j].name,
|
||||||
|
strlen(table->key_info[j].name),
|
||||||
|
system_charset_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Save Query Plan Footprint
|
Save Query Plan Footprint
|
||||||
@ -22982,9 +22997,6 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
for (JOIN_TAB *tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS); tab;
|
for (JOIN_TAB *tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS); tab;
|
||||||
tab= next_breadth_first_tab(join, WALK_OPTIMIZATION_TABS, tab))
|
tab= next_breadth_first_tab(join, WALK_OPTIMIZATION_TABS, tab))
|
||||||
{
|
{
|
||||||
QPF_table_access *qpt= new QPF_table_access;
|
|
||||||
qp_sel->add_table(qpt);
|
|
||||||
|
|
||||||
if (tab->bush_root_tab)
|
if (tab->bush_root_tab)
|
||||||
{
|
{
|
||||||
JOIN_TAB *first_sibling= tab->bush_root_tab->bush_children->start;
|
JOIN_TAB *first_sibling= tab->bush_root_tab->bush_children->start;
|
||||||
@ -23020,7 +23032,6 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (join->table_access_tabs == join->join_tab &&
|
if (join->table_access_tabs == join->join_tab &&
|
||||||
tab == (first_top_tab + join->const_tables) && pre_sort_join_tab)
|
tab == (first_top_tab + join->const_tables) && pre_sort_join_tab)
|
||||||
{
|
{
|
||||||
@ -23028,8 +23039,12 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
tab= pre_sort_join_tab;
|
tab= pre_sort_join_tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPF_table_access *qpt= new QPF_table_access;
|
||||||
|
qp_sel->add_table(qpt);
|
||||||
|
|
||||||
/* id */
|
/* id */
|
||||||
qp_sel->select_id= select_id;
|
// TODO: this can be '2' in case of SJM nests..
|
||||||
|
//qp_sel->select_id= select_id;
|
||||||
|
|
||||||
/* select_type */
|
/* select_type */
|
||||||
//const char* stype= printing_materialize_nest? "MATERIALIZED" :
|
//const char* stype= printing_materialize_nest? "MATERIALIZED" :
|
||||||
@ -23099,6 +23114,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
|
|
||||||
/* Build "possible_keys" value */
|
/* Build "possible_keys" value */
|
||||||
qpt->possible_keys= tab->keys;
|
qpt->possible_keys= tab->keys;
|
||||||
|
append_possible_keys(&qpt->possible_keys_str, table, tab->keys);
|
||||||
|
|
||||||
/* Build "key", "key_len", and "ref" */
|
/* Build "key", "key_len", and "ref" */
|
||||||
|
|
||||||
@ -23379,9 +23395,10 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
*/
|
*/
|
||||||
if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE)
|
if (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE)
|
||||||
{
|
{
|
||||||
qpt->push_extra(ET_USING_MRR);
|
|
||||||
explain_append_mrr_info((QUICK_RANGE_SELECT*)(tab->select->quick),
|
explain_append_mrr_info((QUICK_RANGE_SELECT*)(tab->select->quick),
|
||||||
&qpt->mrr_type);
|
&qpt->mrr_type);
|
||||||
|
if (qpt->mrr_type.length() > 0)
|
||||||
|
qpt->push_extra(ET_USING_MRR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_tmp_table)
|
if (need_tmp_table)
|
||||||
@ -23463,6 +23480,23 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
}
|
}
|
||||||
output->add_node(qp_sel);
|
output->add_node(qp_sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
|
||||||
|
unit;
|
||||||
|
unit= unit->next_unit())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Display subqueries only if they are not parts of eliminated WHERE/ON
|
||||||
|
clauses.
|
||||||
|
*/
|
||||||
|
if (!(unit->item && unit->item->eliminated))
|
||||||
|
{
|
||||||
|
qp_sel->add_child(unit->first_select()->select_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user