Commit 4bed7aa8 authored by Sergey Petrunya's avatar Sergey Petrunya

MDEV-3798: [SHOW] EXPLAIN UPDATE/DELETE, Memory leak in binlog.binlog_base64_flag:

- It turns out, there are statements that will call lex_start(thd->lex) 
  after parsing has been finished. lex_start() will set lex->explain=NULL,
  which will lose the pointer to already allocated Explain_plan object.
- To get rid of this, switch to lazy creation of lex->explain.  Now, it is 
  created only when we get a part ot query plan.
parent 207f0082
......@@ -86,6 +86,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
call might reset the value of current_stmt_binlog_format, so
we need to do any changes to that value after this function.
*/
delete_explain_query(thd->lex);
lex_start(ev_thd);
mysql_reset_thd_for_next_command(ev_thd, 0);
......
......@@ -3246,7 +3246,6 @@ sp_instr_set::execute(THD *thd, uint *nextp)
int
sp_instr_set::exec_core(THD *thd, uint *nextp)
{
create_explain_query(thd->lex, thd->mem_root);
int res= thd->spcont->set_variable(thd, m_offset, &m_value);
if (res)
......
......@@ -228,6 +228,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_plan.using_filesort= FALSE;
DBUG_ENTER("mysql_delete");
create_explain_query(thd->lex, thd->mem_root);
if (open_and_lock_tables(thd, table_list, TRUE, 0))
DBUG_RETURN(TRUE);
......
......@@ -946,3 +946,9 @@ void create_explain_query(LEX *lex, MEM_ROOT *mem_root)
lex->explain->mem_root= mem_root;
}
void create_explain_query_if_not_exists(LEX *lex, MEM_ROOT *mem_root)
{
if (!lex->explain)
create_explain_query(lex, mem_root);
}
......@@ -719,6 +719,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
Item *unused_conds= 0;
DBUG_ENTER("mysql_insert");
create_explain_query(thd->lex, thd->mem_root);
/*
Upgrade lock type if the requested lock is incompatible with
the current connection mode or table operation.
......
......@@ -448,7 +448,7 @@ void lex_start(THD *thd)
lex->thd= lex->unit.thd= thd;
lex->explain= NULL;
DBUG_ASSERT(!lex->explain);
lex->context_stack.empty();
lex->unit.init_query();
......
......@@ -622,6 +622,7 @@ class Explain_query;
void delete_explain_query(LEX *lex);
void create_explain_query(LEX *lex, MEM_ROOT *mem_root);
void create_explain_query_if_not_exists(LEX *lex, MEM_ROOT *mem_root);
bool print_explain_query(LEX *lex, THD *thd, String *str);
class st_select_lex_unit: public st_select_lex_node {
......
......@@ -2201,8 +2201,6 @@ mysql_execute_command(THD *thd)
thd->mdl_context.release_transactional_locks();
}
create_explain_query(thd->lex, thd->mem_root);
#ifndef DBUG_OFF
if (lex->sql_command != SQLCOM_SET_OPTION)
DEBUG_SYNC(thd,"before_execute_sql_command");
......
......@@ -1020,6 +1020,7 @@ int JOIN::optimize()
*/
if (was_optimized != optimized && !res && have_query_plan != QEP_DELETED)
{
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
have_query_plan= QEP_AVAILABLE;
save_explain_data(thd->lex->explain, false /* can overwrite */,
need_tmp,
......
......@@ -632,7 +632,9 @@ bool st_select_lex_unit::exec()
saved_error= optimize();
if (!saved_error && !was_executed && thd->lex->explain)
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
if (!saved_error && !was_executed)
save_union_explain(thd->lex->explain);
if (uncacheable || !item || !item->assigned() || describe)
......@@ -782,7 +784,7 @@ bool st_select_lex_unit::exec()
if (!fake_select_lex->ref_pointer_array)
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
if (!was_executed && thd->lex->explain)
if (!was_executed)
save_union_explain_part2(thd->lex->explain);
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
......
......@@ -281,6 +281,7 @@ int mysql_update(THD *thd,
query_plan.using_filesort= FALSE;
DBUG_ENTER("mysql_update");
create_explain_query(thd->lex, thd->mem_root);
if (open_tables(thd, &table_list, &table_count, 0))
DBUG_RETURN(1);
......
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