[SHOW] EXPLAIN UPDATE/DELETE, code re-structuring
- Handle statements inside SPs: = regular statements = SET command, which does not have its own statement. - Handle execution of subquery from range optimizer: allocate subquery QPFs on the same MEM_ROOT as the whole query plan was allocated.
This commit is contained in:
parent
ab4a13b2b9
commit
af5e128e50
@ -559,8 +559,19 @@ int QPF_update::print_explain(QPF_query *query, select_result_sink *output,
|
|||||||
return print_explain_for_children(query, output, explain_flags);
|
return print_explain_for_children(query, output, explain_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_qpf_query(QPF_query * query)
|
|
||||||
|
void delete_qpf_query(LEX *lex)
|
||||||
{
|
{
|
||||||
delete query;
|
delete lex->query_plan_footprint;
|
||||||
|
lex->query_plan_footprint= NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void create_qpf_query(LEX *lex, MEM_ROOT *mem_root)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(!lex->query_plan_footprint);
|
||||||
|
lex->query_plan_footprint= new QPF_query;
|
||||||
|
DBUG_ASSERT(mem_root == current_thd->mem_root);
|
||||||
|
lex->query_plan_footprint->mem_root= mem_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +214,8 @@ public:
|
|||||||
|
|
||||||
/* Produce a tabular EXPLAIN output */
|
/* Produce a tabular EXPLAIN output */
|
||||||
int print_explain(select_result_sink *output, uint8 explain_flags);
|
int print_explain(select_result_sink *output, uint8 explain_flags);
|
||||||
|
|
||||||
|
MEM_ROOT *mem_root;
|
||||||
private:
|
private:
|
||||||
QPF_union *unions[MAX_TABLES];
|
QPF_union *unions[MAX_TABLES];
|
||||||
QPF_select *selects[MAX_TABLES];
|
QPF_select *selects[MAX_TABLES];
|
||||||
|
@ -2973,6 +2973,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
reinit_stmt_before_use(thd, m_lex);
|
reinit_stmt_before_use(thd, m_lex);
|
||||||
|
// not here, but inside every instr: create_qpf_query(m_lex);
|
||||||
|
|
||||||
if (open_tables)
|
if (open_tables)
|
||||||
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
|
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
|
||||||
@ -3007,8 +3008,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
thd->mdl_context.release_statement_locks();
|
thd->mdl_context.release_statement_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_qpf_query(m_lex->query_plan_footprint);
|
delete_qpf_query(m_lex);
|
||||||
m_lex->query_plan_footprint= NULL;
|
|
||||||
|
|
||||||
if (m_lex->query_tables_own_last)
|
if (m_lex->query_tables_own_last)
|
||||||
{
|
{
|
||||||
@ -3212,6 +3212,7 @@ sp_instr_set::execute(THD *thd, uint *nextp)
|
|||||||
int
|
int
|
||||||
sp_instr_set::exec_core(THD *thd, uint *nextp)
|
sp_instr_set::exec_core(THD *thd, uint *nextp)
|
||||||
{
|
{
|
||||||
|
create_qpf_query(thd->lex, thd->mem_root);
|
||||||
int res= thd->spcont->set_variable(thd, m_offset, &m_value);
|
int res= thd->spcont->set_variable(thd, m_offset, &m_value);
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
@ -3224,6 +3225,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
|
|||||||
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
|
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
delete_qpf_query(thd->lex);
|
||||||
|
|
||||||
*nextp = m_ip+1;
|
*nextp = m_ip+1;
|
||||||
return res;
|
return res;
|
||||||
|
@ -4251,7 +4251,7 @@ void st_select_lex::save_qpf(QPF_query *output)
|
|||||||
msg= "Query plan already deleted";
|
msg= "Query plan already deleted";
|
||||||
}
|
}
|
||||||
set_explain_type(TRUE/* on_the_fly */);
|
set_explain_type(TRUE/* on_the_fly */);
|
||||||
QPF_select *qp_sel= new QPF_select;
|
QPF_select *qp_sel= new (output->mem_root) QPF_select;
|
||||||
qp_sel->select_id= select_number;
|
qp_sel->select_id= select_number;
|
||||||
qp_sel->select_type= type;
|
qp_sel->select_type= type;
|
||||||
qp_sel->message= msg;
|
qp_sel->message= msg;
|
||||||
@ -4346,7 +4346,7 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPF_union *qpfu= new QPF_union;
|
QPF_union *qpfu= new (output->mem_root) QPF_union;
|
||||||
/*
|
/*
|
||||||
TODO: The following code should be eliminated. If we have a capability to
|
TODO: The following code should be eliminated. If we have a capability to
|
||||||
save Query Plan Footprints, we should just save them, and never need to
|
save Query Plan Footprints, we should just save them, and never need to
|
||||||
@ -4361,7 +4361,7 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
|
|||||||
const char *msg="Query plan already deleted";
|
const char *msg="Query plan already deleted";
|
||||||
first->set_explain_type(TRUE/* on_the_fly */);
|
first->set_explain_type(TRUE/* on_the_fly */);
|
||||||
|
|
||||||
QPF_select *qp_sel= new QPF_select;
|
QPF_select *qp_sel= new (output->mem_root)QPF_select;
|
||||||
qp_sel->select_id= first->select_number;
|
qp_sel->select_id= first->select_number;
|
||||||
qp_sel->select_type= first->type;
|
qp_sel->select_type= first->type;
|
||||||
qp_sel->message= msg;
|
qp_sel->message= msg;
|
||||||
|
@ -619,7 +619,8 @@ class select_union;
|
|||||||
class Procedure;
|
class Procedure;
|
||||||
class QPF_query;
|
class QPF_query;
|
||||||
|
|
||||||
void delete_qpf_query(QPF_query * query);
|
void delete_qpf_query(LEX *lex);
|
||||||
|
void create_qpf_query(LEX *lex, MEM_ROOT *mem_root);
|
||||||
|
|
||||||
class st_select_lex_unit: public st_select_lex_node {
|
class st_select_lex_unit: public st_select_lex_node {
|
||||||
protected:
|
protected:
|
||||||
|
@ -598,10 +598,7 @@ static void handle_bootstrap_impl(THD *thd)
|
|||||||
#if defined(ENABLED_PROFILING)
|
#if defined(ENABLED_PROFILING)
|
||||||
thd->profiling.finish_current_query();
|
thd->profiling.finish_current_query();
|
||||||
#endif
|
#endif
|
||||||
//
|
delete_qpf_query(thd->lex);
|
||||||
delete thd->lex->query_plan_footprint;
|
|
||||||
thd->lex->query_plan_footprint= NULL;
|
|
||||||
//
|
|
||||||
|
|
||||||
if (bootstrap_error)
|
if (bootstrap_error)
|
||||||
break;
|
break;
|
||||||
@ -1523,8 +1520,7 @@ void log_slow_statement(THD *thd)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("log_slow_statement");
|
DBUG_ENTER("log_slow_statement");
|
||||||
|
|
||||||
delete thd->lex->query_plan_footprint;
|
delete_qpf_query(thd->lex);
|
||||||
thd->lex->query_plan_footprint= NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following should never be true with our current code base,
|
The following should never be true with our current code base,
|
||||||
@ -2188,8 +2184,7 @@ mysql_execute_command(THD *thd)
|
|||||||
thd->mdl_context.release_transactional_locks();
|
thd->mdl_context.release_transactional_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_ASSERT(!thd->lex->query_plan_footprint);
|
create_qpf_query(thd->lex, thd->mem_root);
|
||||||
thd->lex->query_plan_footprint= new QPF_query;
|
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
if (lex->sql_command != SQLCOM_SET_OPTION)
|
if (lex->sql_command != SQLCOM_SET_OPTION)
|
||||||
|
@ -3927,8 +3927,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
|||||||
if (! cursor)
|
if (! cursor)
|
||||||
cleanup_stmt();
|
cleanup_stmt();
|
||||||
//psergey: TODO the "EXECUTE problem" is here
|
//psergey: TODO the "EXECUTE problem" is here
|
||||||
delete_qpf_query(thd->lex->query_plan_footprint);
|
delete_qpf_query(thd->lex);
|
||||||
thd->lex->query_plan_footprint= NULL;
|
|
||||||
|
|
||||||
thd->set_statement(&stmt_backup);
|
thd->set_statement(&stmt_backup);
|
||||||
thd->stmt_arena= old_stmt_arena;
|
thd->stmt_arena= old_stmt_arena;
|
||||||
|
@ -11112,6 +11112,7 @@ void JOIN::cleanup(bool full)
|
|||||||
if (select_lex->select_number != UINT_MAX &&
|
if (select_lex->select_number != UINT_MAX &&
|
||||||
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
|
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
|
||||||
have_query_plan != QEP_NOT_PRESENT_YET &&
|
have_query_plan != QEP_NOT_PRESENT_YET &&
|
||||||
|
thd->lex->query_plan_footprint && // for "SET" command in SPs.
|
||||||
!thd->lex->query_plan_footprint->get_select(select_lex->select_number))
|
!thd->lex->query_plan_footprint->get_select(select_lex->select_number))
|
||||||
{
|
{
|
||||||
const char *message= NULL;
|
const char *message= NULL;
|
||||||
@ -22986,7 +22987,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
if (message)
|
if (message)
|
||||||
{
|
{
|
||||||
QPF_select *qp_sel;
|
QPF_select *qp_sel;
|
||||||
qp_node= qp_sel= new QPF_select;
|
qp_node= qp_sel= new (output->mem_root) QPF_select;
|
||||||
join->select_lex->set_explain_type(on_the_fly);
|
join->select_lex->set_explain_type(on_the_fly);
|
||||||
|
|
||||||
qp_sel->select_id= join->select_lex->select_number;
|
qp_sel->select_id= join->select_lex->select_number;
|
||||||
@ -22998,7 +22999,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
else if (join->select_lex == join->unit->fake_select_lex)
|
else if (join->select_lex == join->unit->fake_select_lex)
|
||||||
{
|
{
|
||||||
select_lex->set_explain_type(on_the_fly);
|
select_lex->set_explain_type(on_the_fly);
|
||||||
QPF_union *qp_union= new QPF_union;
|
QPF_union *qp_union= new (output->mem_root) QPF_union;
|
||||||
qp_node= qp_union;
|
qp_node= qp_union;
|
||||||
|
|
||||||
SELECT_LEX *child;
|
SELECT_LEX *child;
|
||||||
@ -23018,7 +23019,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
|||||||
join->select_lex->master_unit()->derived->is_materialized_derived())
|
join->select_lex->master_unit()->derived->is_materialized_derived())
|
||||||
{
|
{
|
||||||
QPF_select *qp_sel;
|
QPF_select *qp_sel;
|
||||||
qp_node= qp_sel= new QPF_select;
|
qp_node= qp_sel= new (output->mem_root) QPF_select;
|
||||||
table_map used_tables=0;
|
table_map used_tables=0;
|
||||||
|
|
||||||
if (on_the_fly)
|
if (on_the_fly)
|
||||||
@ -23077,7 +23078,7 @@ 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;
|
QPF_table_access *qpt= new (output->mem_root) QPF_table_access;
|
||||||
qp_sel->add_table(qpt);
|
qp_sel->add_table(qpt);
|
||||||
|
|
||||||
/* id */
|
/* id */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user