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)
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;
......
......@@ -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);
/**
......
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