summaryrefslogtreecommitdiff
path: root/sql/sp_rcontext.cc
diff options
context:
space:
mode:
authorunknown <malff/marcsql@weblab.(none)>2006-08-02 22:18:49 -0700
committerunknown <malff/marcsql@weblab.(none)>2006-08-02 22:18:49 -0700
commitf748b69134c62cfd1767357b7f4adeb7e990ee2e (patch)
tree987c7b7c3125c669d39ab406692b81e733eea48c /sql/sp_rcontext.cc
parentd57c41b79d972012ae76fe0b36ee31b1e97989ef (diff)
downloadmariadb-git-f748b69134c62cfd1767357b7f4adeb7e990ee2e.tar.gz
Bug#8153 (Stored procedure with subquery and continue handler, wrong result)
Before this fix, - a runtime error in a statement in a stored procedure with no error handlers was properly detected (as expected) - a runtime error in a statement with an error handler inherited from a non local runtime context (i.e., proc a with a handler, calling proc b) was properly detected (as expected) - a runtime error in a statement with a *local* error handler was executed as follows : a) the statement would succeed, regardless of the error condition, (bug) b) the error handler would be called (as expected). The root cause is that functions like my_messqge_sql would "forget" to set the thread flag thd->net.report_error to 1, because of the check involving sp_rcontext::found_handler_here(). Failure to set this flag would cause, later in the call stack, in Item_func::fix_fields() at line 190, the code to return FALSE and consider that executing the statement was successful. With this fix : - error handling code, that was duplicated in different places in the code, is now implemented in sp_rcontext::handle_error(), - handle_error() correctly sets thd->net.report_error when a handler is present, regardless of the handler location (local, or in the call stack). A test case, bug8153_subselect, has been written to demonstrate the change of behavior before and after the fix. Another test case, bug8153_function_a, as also been writen. This test has the same behavior before and after the fix. This test has been written to demonstrate that the previous expected result of procedure bug18787, was incorrect, since select no_such_function() should fail and therefore not produce a result. The incorrect result for bug18787 has the same root cause as Bug#8153, and the expected result has been adjusted. sql/mysqld.cc: Bug#8153, use sp_rcontext::handle_error() to handle errors. sql/sql_error.cc: Bug#8153, use sp_rcontext::handle_error() to handle errors. sql/protocol.cc: Bug#8153, use sp_rcontext::handle_error() to handle errors. sql/sp_rcontext.h: Bug#8153, created helper sp_rcontext::handle_error() to handle errors. sql/sp_rcontext.cc: Bug#8153, created helper sp_rcontext::handle_error() to handle errors. mysql-test/t/sp.test: Bug#8153, added test cases. mysql-test/r/sp.result: Bug#8153, added test cases, fixed expected result of bug18787.
Diffstat (limited to 'sql/sp_rcontext.cc')
-rw-r--r--sql/sp_rcontext.cc59
1 files changed, 59 insertions, 0 deletions
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 3bc27a029d0..67ee5459bb4 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -260,6 +260,65 @@ sp_rcontext::find_handler(uint sql_errno,
return TRUE;
}
+/*
+ Handle the error for a given errno.
+ The severity of the error is adjusted depending of the current sql_mode.
+ If an handler is present for the error (see find_handler()),
+ this function will return true.
+ If a handler is found and if the severity of the error indicate
+ that the current instruction executed should abort,
+ the flag thd->net.report_error is also set.
+ This will cause the execution of the current instruction in a
+ sp_instr* to fail, and give control to the handler code itself
+ in the sp_head::execute() loop.
+
+ SYNOPSIS
+ sql_errno The error code
+ level Warning level
+ thd The current thread
+ - thd->net.report_error is an optional output.
+
+ RETURN
+ TRUE if a handler was found.
+ FALSE if no handler was found.
+*/
+bool
+sp_rcontext::handle_error(uint sql_errno,
+ MYSQL_ERROR::enum_warning_level level,
+ THD *thd)
+{
+ bool handled= FALSE;
+ MYSQL_ERROR::enum_warning_level elevated_level= level;
+
+
+ /* Depending on the sql_mode of execution,
+ warnings may be considered errors */
+ if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
+ thd->really_abort_on_warning())
+ {
+ elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ }
+
+ if (find_handler(sql_errno, elevated_level))
+ {
+ if (elevated_level == MYSQL_ERROR::WARN_LEVEL_ERROR)
+ {
+ /*
+ Forces to abort the current instruction execution.
+ NOTE: This code is altering the original meaning of
+ the net.report_error flag (send an error to the client).
+ In the context of stored procedures with error handlers,
+ the flag is reused to cause error propagation,
+ until the error handler is reached.
+ No messages will be sent to the client in that context.
+ */
+ thd->net.report_error= 1;
+ }
+ handled= TRUE;
+ }
+
+ return handled;
+}
void
sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)