diff options
author | Dmitry Shulga <dmitry.shulga@mariadb.com> | 2023-02-27 12:10:56 +0700 |
---|---|---|
committer | Dmitry Shulga <dmitry.shulga@mariadb.com> | 2023-02-27 12:10:56 +0700 |
commit | c197117242b3235108dc847d0fc7c3dab2f2037e (patch) | |
tree | 7329b1efa95489cb58dd48b1cfcb26f0d5839425 | |
parent | 99973403edc57f113114aa9724043b476a6836ae (diff) | |
download | mariadb-git-c197117242b3235108dc847d0fc7c3dab2f2037e.tar.gz |
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 SP instruction's a 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().
-rw-r--r-- | sql/sp_instr.cc | 28 | ||||
-rw-r--r-- | sql/sp_instr.h | 2 |
2 files changed, 25 insertions, 5 deletions
diff --git a/sql/sp_instr.cc b/sql/sp_instr.cc index aa6ce20cada..7f1cd1c9ea5 100644 --- a/sql/sp_instr.cc +++ b/sql/sp_instr.cc @@ -193,8 +193,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 @@ -206,7 +209,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"); @@ -232,7 +236,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) { @@ -422,6 +439,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) { @@ -440,6 +458,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; @@ -455,7 +474,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 794e9b2ff6c..3fccd1c826a 100644 --- a/sql/sp_instr.h +++ b/sql/sp_instr.h @@ -254,7 +254,7 @@ public: */ int reset_lex_and_exec_core(THD *thd, uint *nextp, bool open_tables, - sp_instr* instr); + sp_instr* instr, bool rerun_the_same_instr); /** |