Commit 6abc16cb authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-5816: Stored programs: validation of stored program statements

This patch fixes the issue with missing warnings generated on re-parsing
a failing SP instruction's statement. That is, any warning generated
on re-parsing a statement was discarded after a SP instruction's statement
has been successfully re-parsed.

The reason for discarding warnings after re-parsing is that the method
  THD::set_query_id()
called every time when a failing SP instruction re-parsed.
In result,
  Warning_info::m_warn_id != thd->query_id
and when the method
  Diagnostics_area::opt_clear_warning_info(thd->query_id)
is invoked from sp_head::execute all warnings accumulated during
execution of the current SP instruction is cleared.

So, to fix the issue invokes the method THD::set_query_id()
once per SP instruction, on its first execution. Re-parsing of failing
SP instruction and following run of it don't invoke the method
THD::set_query_id().
parent 1ee1979e
...@@ -191,8 +191,11 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) ...@@ -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 list and open and lock them (used in instructions which
need to calculate some expression and don't execute need to calculate some expression and don't execute
complete statement). 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. 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 @note
We are not saving/restoring some parts of THD which may need this because 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) ...@@ -204,7 +207,8 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
int int
sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, 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; int res= 0;
DBUG_ENTER("reset_lex_and_exec_core"); DBUG_ENTER("reset_lex_and_exec_core");
...@@ -230,7 +234,20 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, ...@@ -230,7 +234,20 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
*/ */
thd->lex= m_lex; 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) 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, ...@@ -420,6 +437,7 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp,
sp_lex_instr* instr) sp_lex_instr* instr)
{ {
Reprepare_observer reprepare_observer; Reprepare_observer reprepare_observer;
bool rerun_the_same_instr= false;
while (true) while (true)
{ {
...@@ -438,6 +456,7 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp, ...@@ -438,6 +456,7 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp,
set_lex(lex); set_lex(lex);
m_first_execution= true; m_first_execution= true;
rerun_the_same_instr= true;
} }
Reprepare_observer *stmt_reprepare_observer= nullptr; Reprepare_observer *stmt_reprepare_observer= nullptr;
...@@ -453,7 +472,8 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp, ...@@ -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; Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
thd->m_reprepare_observer= stmt_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; thd->m_reprepare_observer= save_reprepare_observer;
......
...@@ -262,7 +262,7 @@ class sp_lex_keeper final ...@@ -262,7 +262,7 @@ class sp_lex_keeper final
@todo Conflicting comment in sp_head.cc @todo Conflicting comment in sp_head.cc
*/ */
int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables,
sp_instr* instr); sp_instr* instr, bool rerun_the_same_instr);
/** /**
......
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