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 ...@@ -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 call might reset the value of current_stmt_binlog_format, so
we need to do any changes to that value after this function. we need to do any changes to that value after this function.
*/ */
delete_explain_query(thd->lex);
lex_start(ev_thd); lex_start(ev_thd);
mysql_reset_thd_for_next_command(ev_thd, 0); mysql_reset_thd_for_next_command(ev_thd, 0);
......
...@@ -3246,7 +3246,6 @@ sp_instr_set::execute(THD *thd, uint *nextp) ...@@ -3246,7 +3246,6 @@ 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_explain_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)
......
...@@ -228,6 +228,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -228,6 +228,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
query_plan.using_filesort= FALSE; query_plan.using_filesort= FALSE;
DBUG_ENTER("mysql_delete"); DBUG_ENTER("mysql_delete");
create_explain_query(thd->lex, thd->mem_root);
if (open_and_lock_tables(thd, table_list, TRUE, 0)) if (open_and_lock_tables(thd, table_list, TRUE, 0))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
......
...@@ -946,3 +946,9 @@ void create_explain_query(LEX *lex, MEM_ROOT *mem_root) ...@@ -946,3 +946,9 @@ void create_explain_query(LEX *lex, MEM_ROOT *mem_root)
lex->explain->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, ...@@ -719,6 +719,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
Item *unused_conds= 0; Item *unused_conds= 0;
DBUG_ENTER("mysql_insert"); DBUG_ENTER("mysql_insert");
create_explain_query(thd->lex, thd->mem_root);
/* /*
Upgrade lock type if the requested lock is incompatible with Upgrade lock type if the requested lock is incompatible with
the current connection mode or table operation. the current connection mode or table operation.
......
...@@ -448,7 +448,7 @@ void lex_start(THD *thd) ...@@ -448,7 +448,7 @@ void lex_start(THD *thd)
lex->thd= lex->unit.thd= thd; lex->thd= lex->unit.thd= thd;
lex->explain= NULL; DBUG_ASSERT(!lex->explain);
lex->context_stack.empty(); lex->context_stack.empty();
lex->unit.init_query(); lex->unit.init_query();
......
...@@ -622,6 +622,7 @@ class Explain_query; ...@@ -622,6 +622,7 @@ class Explain_query;
void delete_explain_query(LEX *lex); void delete_explain_query(LEX *lex);
void create_explain_query(LEX *lex, MEM_ROOT *mem_root); 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); bool print_explain_query(LEX *lex, THD *thd, String *str);
class st_select_lex_unit: public st_select_lex_node { class st_select_lex_unit: public st_select_lex_node {
......
...@@ -2201,8 +2201,6 @@ mysql_execute_command(THD *thd) ...@@ -2201,8 +2201,6 @@ mysql_execute_command(THD *thd)
thd->mdl_context.release_transactional_locks(); thd->mdl_context.release_transactional_locks();
} }
create_explain_query(thd->lex, thd->mem_root);
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (lex->sql_command != SQLCOM_SET_OPTION) if (lex->sql_command != SQLCOM_SET_OPTION)
DEBUG_SYNC(thd,"before_execute_sql_command"); DEBUG_SYNC(thd,"before_execute_sql_command");
......
...@@ -1020,6 +1020,7 @@ int JOIN::optimize() ...@@ -1020,6 +1020,7 @@ int JOIN::optimize()
*/ */
if (was_optimized != optimized && !res && have_query_plan != QEP_DELETED) 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; have_query_plan= QEP_AVAILABLE;
save_explain_data(thd->lex->explain, false /* can overwrite */, save_explain_data(thd->lex->explain, false /* can overwrite */,
need_tmp, need_tmp,
......
...@@ -632,7 +632,9 @@ bool st_select_lex_unit::exec() ...@@ -632,7 +632,9 @@ bool st_select_lex_unit::exec()
saved_error= optimize(); 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); save_union_explain(thd->lex->explain);
if (uncacheable || !item || !item->assigned() || describe) if (uncacheable || !item || !item->assigned() || describe)
...@@ -782,7 +784,7 @@ bool st_select_lex_unit::exec() ...@@ -782,7 +784,7 @@ bool st_select_lex_unit::exec()
if (!fake_select_lex->ref_pointer_array) if (!fake_select_lex->ref_pointer_array)
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items; 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); save_union_explain_part2(thd->lex->explain);
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array, saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
......
...@@ -281,6 +281,7 @@ int mysql_update(THD *thd, ...@@ -281,6 +281,7 @@ int mysql_update(THD *thd,
query_plan.using_filesort= FALSE; query_plan.using_filesort= FALSE;
DBUG_ENTER("mysql_update"); DBUG_ENTER("mysql_update");
create_explain_query(thd->lex, thd->mem_root);
if (open_tables(thd, &table_list, &table_count, 0)) if (open_tables(thd, &table_list, &table_count, 0))
DBUG_RETURN(1); 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