Skip to content

Commit

Permalink
Bug#30561920 - HANDLER FAILS TO TRIGGER ON ERROR 1049 OR SQLSTATE 420…
Browse files Browse the repository at this point in the history
…00 OR PLAIN SQLEXCEPTION

Issue here is, if an error handler is defined in a stored program
then error condition for trying to access a non-existing table
is handled. But if a stored program statement tries to access
table from non-existing database then error is not handled by
the error handler.

While opening table for a stored program, if a table is not found
then error is ignored using internal error handler. The real
failure occurs when statement attempts to use the table. Error
is handled by the stored program error handler at this stage.
Internal error handler used to ignore error at table open stage
currently handles only error reported for non-existing table.
Error reported for non-existing database is not handled by it.
Due to which error is reported much before stored program
error handlers can be invoked.

To fix this issue, extended internal error handler to ignore
even error reported for non-existing database.

Thanks to Kamil Holubicki for contributing a patch for this issue.

Change-Id: I4e78904120a0af6012fab2db94bbb66133c66fda
  • Loading branch information
phulakun committed Jan 8, 2020
1 parent 6273d52 commit 72c6171
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 6 deletions.
26 changes: 26 additions & 0 deletions mysql-test/r/sp-bugs.result
Original file line number Diff line number Diff line change
Expand Up @@ -502,3 +502,29 @@ EXECUTE stmt USING @var;
CONCAT(UNIX_TIMESTAMP(?))
1546290000
DEALLOCATE PREPARE stmt;
#
# Bug#30561920 - Handler fails to trigger on error 1049 or SQLSTATE 42000
# or plain SQLEXCEPTION
#
CREATE FUNCTION func1() RETURNS INT
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN NULL;
SELECT * INTO @a FROM fake_table;
RETURN 1;
END|
CREATE FUNCTION func2() RETURNS INT
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN NULL;
SELECT * INTO @a FROM fake_db.fake_table;
RETURN 1;
END|
SELECT func1();
func1()
NULL
# Without fix, exit handler is not triggered and unknown DB error
# is reported.
SELECT func2();
func2()
NULL
DROP FUNCTION func1;
DROP FUNCTION func2;
29 changes: 29 additions & 0 deletions mysql-test/t/sp-bugs.test
Original file line number Diff line number Diff line change
Expand Up @@ -505,3 +505,32 @@ EXECUTE stmt USING @var;
SET @var = '2019-01-01 00:00:00';
EXECUTE stmt USING @var;
DEALLOCATE PREPARE stmt;


--echo #
--echo # Bug#30561920 - Handler fails to trigger on error 1049 or SQLSTATE 42000
--echo # or plain SQLEXCEPTION
--echo #
DELIMITER |;
CREATE FUNCTION func1() RETURNS INT
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN NULL;
SELECT * INTO @a FROM fake_table;
RETURN 1;
END|

CREATE FUNCTION func2() RETURNS INT
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN NULL;
SELECT * INTO @a FROM fake_db.fake_table;
RETURN 1;
END|
DELIMITER ;|

SELECT func1();
--echo # Without fix, exit handler is not triggered and unknown DB error
--echo # is reported.
SELECT func2();

DROP FUNCTION func1;
DROP FUNCTION func2;
13 changes: 7 additions & 6 deletions sql/error_handler.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
Expand Down Expand Up @@ -209,7 +209,7 @@ class View_error_handler : public Internal_error_handler {
};

/**
This internal handler is used to trap ER_NO_SUCH_TABLE.
This internal handler is used to trap ER_NO_SUCH_TABLE and ER_BAD_DB_ERROR.
*/

class No_such_table_error_handler : public Internal_error_handler {
Expand All @@ -219,7 +219,7 @@ class No_such_table_error_handler : public Internal_error_handler {
virtual bool handle_condition(THD *, uint sql_errno, const char *,
Sql_condition::enum_severity_level *,
const char *) {
if (sql_errno == ER_NO_SUCH_TABLE) {
if (sql_errno == ER_BAD_DB_ERROR || sql_errno == ER_NO_SUCH_TABLE) {
m_handled_errors++;
return true;
}
Expand All @@ -229,14 +229,15 @@ class No_such_table_error_handler : public Internal_error_handler {
}

/**
Returns true if one or more ER_NO_SUCH_TABLE errors have been
trapped and no other errors have been seen. false otherwise.
Returns true if one or more ER_NO_SUCH_TABLE and ER_BAD_DB_ERROR errors have
been trapped and no other errors have been seen. false otherwise.
*/
bool safely_trapped_errors() const {
/*
If m_unhandled_errors != 0, something else, unanticipated, happened,
so the error is not trapped but returned to the caller.
Multiple ER_NO_SUCH_TABLE can be raised in case of views.
Multiple ER_NO_SUCH_TABLE and ER_BAD_DB_ERROR can be raised in case of
views.
*/
return ((m_handled_errors > 0) && (m_unhandled_errors == 0));
}
Expand Down

0 comments on commit 72c6171

Please sign in to comment.