diff --git a/sql/sp_instr.cc b/sql/sp_instr.cc index a40e7d0866ade..f8bc34c3df0be 100644 --- a/sql/sp_instr.cc +++ b/sql/sp_instr.cc @@ -191,8 +191,11 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) list and open and lock them (used in instructions which need to calculate some expression and don't execute complete statement). - @param sp_instr instruction for which we prepare context, and which core + @param instr instruction for which we prepare context, and which core function execute by calling its exec_core() method. + @param rerun_the_same_instr true in case the instruction is re-run after + a SQL statement associated with it has been + re-parsed. @note We are not saving/restoring some parts of THD which may need this because @@ -204,7 +207,8 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) int sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, - bool open_tables, sp_instr* instr) + bool open_tables, sp_instr* instr, + bool rerun_the_same_instr) { int res= 0; DBUG_ENTER("reset_lex_and_exec_core"); @@ -230,7 +234,20 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, */ thd->lex= m_lex; - thd->set_query_id(next_query_id()); + /* + If the instruction is re-run by a reason of metadata change, then re-use + current query id rather than set a new one. Doing this way we retain + warnings generated on running the SP instruction. If a new query id was set + it would result in clearing all accumulated warnings in + mysql_execute_command + on calling + thd->get_stmt_da()->opt_clear_warning_info(thd->query_id) + since in this case Warning_info::m_warn_id != thd->query_id. + + @sa Warning_info::opt_clear() + */ + if (!rerun_the_same_instr) + thd->set_query_id(next_query_id()); if (thd->locked_tables_mode <= LTM_LOCK_TABLES) { @@ -420,6 +437,7 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp, sp_lex_instr* instr) { Reprepare_observer reprepare_observer; + bool rerun_the_same_instr= false; while (true) { @@ -438,6 +456,7 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp, set_lex(lex); m_first_execution= true; + rerun_the_same_instr= true; } Reprepare_observer *stmt_reprepare_observer= nullptr; @@ -453,7 +472,8 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp, Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; thd->m_reprepare_observer= stmt_reprepare_observer; - bool rc= reset_lex_and_exec_core(thd, nextp, open_tables, instr); + bool rc= reset_lex_and_exec_core(thd, nextp, open_tables, instr, + rerun_the_same_instr); thd->m_reprepare_observer= save_reprepare_observer; diff --git a/sql/sp_instr.h b/sql/sp_instr.h index 404afcf9b1b29..777c441755f59 100644 --- a/sql/sp_instr.h +++ b/sql/sp_instr.h @@ -262,7 +262,7 @@ class sp_lex_keeper final @todo Conflicting comment in sp_head.cc */ int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, - sp_instr* instr); + sp_instr* instr, bool rerun_the_same_instr); /**