Bug #38806 Wrong scope for SQL HANDLERS in SP

Submitted: 14 Aug 2008 16:40 Modified: 16 Oct 2011 22:29
Reporter: Marc ALFF Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Stored Routines Severity:S2 (Serious)
Version:5.0 and up OS:Any
Assigned to: Alexander Nozdrin CPU Architecture:Any

[14 Aug 2008 16:40] Marc ALFF
Description:
The scope of an exception handler in a stored procedure should not cover
instructions present in other exception handlers in the same level.

For example, in

create procedure p()
begin
  declare continue handler for XXX
  begin
    -- body of HANDLER H1
  end;

  declare continue handler for YYY
  begin
    -- body of HANDLER H2
  end;

  -- body of p()
end

Expected:
The scope of H1 is P
The scope of H2 is P

A SQL condition raised by P can be caught by H1 or H2
A SQL condition raised by H1 or H2 can *not* be caught by H2 or H1

Actual:
The scope of H1 and H2 is (H1 + H2 + P), wrong

A SQL condition raised by P can be caught by H1 or H2 (ok)
A SQL condition raised by H1 or H2 is caught by H2 or H1 (wrong)

How to repeat:
delimiter //
drop procedure if exists p//
drop table if exists t1, t2//
create table t1 (s1 smallint)//
create table t2 (s1 smallint)//
create procedure p()
begin
  declare continue handler for sqlwarning
    create table t2 (s1 int);
  declare continue handler for sqlexception
    insert into t1 values (99999);
  create table t1 (s1 int);
  end//
call p()//
Result: "ERROR 1050 (42S01): Table 't2' already exists".
Apparently the exception handler's INSERT was caught
by the warning handler.
[14 Aug 2008 22:01] MySQL Verification Team
Thank you for the bug report. Verified as described.

Server version: 5.0.70-nt-debug-log Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql 5.0 > use test
Database changed
mysql 5.0 > delimiter //
mysql 5.0 > drop procedure if exists p//
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql 5.0 > drop table if exists t1, t2//
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql 5.0 > create table t1 (s1 smallint)//
Query OK, 0 rows affected (0.08 sec)

mysql 5.0 > create table t2 (s1 smallint)//
Query OK, 0 rows affected (0.06 sec)

mysql 5.0 > create procedure p()
    -> begin
    ->   declare continue handler for sqlwarning
    ->     create table t2 (s1 int);
    ->   declare continue handler for sqlexception
    ->     insert into t1 values (99999);
    ->   create table t1 (s1 int);
    ->   end//
Query OK, 0 rows affected (0.03 sec)

mysql 5.0 > call p()//
ERROR 1050 (42S01): Table 't2' already exists
mysql 5.0 >
[24 Jun 2009 11:59] Georgi Kodinov
Here's how imho we should fix it :

Data structures :
 1. we should get rid of the m_in_handler/m_ihsp stuff : it's a hack
 2. we should be able to keep a stack of m_handler/m_hcount : for this purpose I propose we create a new structure for the m_hstack and keep copies of the combination of m_handler/m_hcont in it (together with the return ip as we do now) : 
struct cont_handler_t {
  sp_handler_t *m_saved_handler;
  uint m_saved_hcount;
  uint m_return_ip;
}
And we change m_hstack's definition to be : 
struct cont_handler_t *m_hstack;

Algorithm (change places):
- on jumping to a continue exception (in sp_head::excute()) we should preserve the current m_handler/m_hcount (together with the return ip) into the m_hstack
- on jumping to a exception we should take out all the handlers (by effectively executing what sp_instr_hpop::execute does) from the current parse context up to the common ancestor context of the handler we're jumping into and the current instruction (the output of the sp_pcontext::diff_handlers)
- on sp_instr_hreturn() for continue handlers we should restore the m_handler/m_hcount from the stack together with the sp

This will allow us to handle more complex examples e.g. like this one : 

  7 create procedure p()
  8 begin
  9   declare continue handler for 1 
 10   begin
 11     signal 1;
 12   end  
 13   declare continue handler for 2
 14   begin
 15     declare continue handler for 3
 16     begin
 17       print;
 18     end  
 19     signal 3
 20   end;  
 21   signal 2;
 22 end//
[24 Jun 2009 12:25] Georgi Kodinov
See related bug #23032
[7 Jul 2009 8:58] Konstantin Osipov
See related Bug#36185
[7 Jul 2009 9:00] Konstantin Osipov
This is a group of bugs that needs to be fixed together. 
The fix depends on a fix for Bug#36649, which is only present in 5.4.
[9 Aug 2010 17:42] Peter Gulutzan
The error is still present with the described 'how to repeat',
with mysql-trunk-bugfixing, pulled today.
[14 Oct 2010 12:35] Alexander Nozdrin
Typo: related to Bug#55852.
[16 Oct 2011 22:29] Paul DuBois
Noted in 5.6.4 changelog.

If multiple handlers existed at the same level within a stored
program, the wrong one could be chosen.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.045 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.