mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
[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:
@ -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);
|
||||
}
|
||||
|
||||
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 */
|
||||
int print_explain(select_result_sink *output, uint8 explain_flags);
|
||||
|
||||
MEM_ROOT *mem_root;
|
||||
private:
|
||||
QPF_union *unions[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);
|
||||
// not here, but inside every instr: create_qpf_query(m_lex);
|
||||
|
||||
if (open_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();
|
||||
}
|
||||
|
||||
delete_qpf_query(m_lex->query_plan_footprint);
|
||||
m_lex->query_plan_footprint= NULL;
|
||||
delete_qpf_query(m_lex);
|
||||
|
||||
if (m_lex->query_tables_own_last)
|
||||
{
|
||||
@ -3212,6 +3212,7 @@ sp_instr_set::execute(THD *thd, uint *nextp)
|
||||
int
|
||||
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);
|
||||
|
||||
if (res)
|
||||
@ -3224,6 +3225,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
|
||||
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
|
||||
}
|
||||
}
|
||||
delete_qpf_query(thd->lex);
|
||||
|
||||
*nextp = m_ip+1;
|
||||
return res;
|
||||
|
@ -4251,7 +4251,7 @@ void st_select_lex::save_qpf(QPF_query *output)
|
||||
msg= "Query plan already deleted";
|
||||
}
|
||||
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_type= type;
|
||||
qp_sel->message= msg;
|
||||
@ -4346,7 +4346,7 @@ int st_select_lex_unit::save_qpf(QPF_query *output)
|
||||
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
|
||||
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";
|
||||
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_type= first->type;
|
||||
qp_sel->message= msg;
|
||||
|
@ -619,7 +619,8 @@ class select_union;
|
||||
class Procedure;
|
||||
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 {
|
||||
protected:
|
||||
|
@ -598,10 +598,7 @@ static void handle_bootstrap_impl(THD *thd)
|
||||
#if defined(ENABLED_PROFILING)
|
||||
thd->profiling.finish_current_query();
|
||||
#endif
|
||||
//
|
||||
delete thd->lex->query_plan_footprint;
|
||||
thd->lex->query_plan_footprint= NULL;
|
||||
//
|
||||
delete_qpf_query(thd->lex);
|
||||
|
||||
if (bootstrap_error)
|
||||
break;
|
||||
@ -1523,8 +1520,7 @@ void log_slow_statement(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("log_slow_statement");
|
||||
|
||||
delete thd->lex->query_plan_footprint;
|
||||
thd->lex->query_plan_footprint= NULL;
|
||||
delete_qpf_query(thd->lex);
|
||||
|
||||
/*
|
||||
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();
|
||||
}
|
||||
|
||||
DBUG_ASSERT(!thd->lex->query_plan_footprint);
|
||||
thd->lex->query_plan_footprint= new QPF_query;
|
||||
create_qpf_query(thd->lex, thd->mem_root);
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
if (lex->sql_command != SQLCOM_SET_OPTION)
|
||||
|
@ -3927,8 +3927,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
||||
if (! cursor)
|
||||
cleanup_stmt();
|
||||
//psergey: TODO the "EXECUTE problem" is here
|
||||
delete_qpf_query(thd->lex->query_plan_footprint);
|
||||
thd->lex->query_plan_footprint= NULL;
|
||||
delete_qpf_query(thd->lex);
|
||||
|
||||
thd->set_statement(&stmt_backup);
|
||||
thd->stmt_arena= old_stmt_arena;
|
||||
|
@ -11112,6 +11112,7 @@ void JOIN::cleanup(bool full)
|
||||
if (select_lex->select_number != UINT_MAX &&
|
||||
select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ &&
|
||||
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))
|
||||
{
|
||||
const char *message= NULL;
|
||||
@ -22986,7 +22987,7 @@ int JOIN::save_qpf(QPF_query *output, bool need_tmp_table, bool need_order,
|
||||
if (message)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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())
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
QPF_table_access *qpt= new QPF_table_access;
|
||||
QPF_table_access *qpt= new (output->mem_root) QPF_table_access;
|
||||
qp_sel->add_table(qpt);
|
||||
|
||||
/* id */
|
||||
|
Reference in New Issue
Block a user