Below is the list of changes that have just been committed into a local
5.0 repository of thek. When thek does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-05-02 14:25:01+02:00, thek@adventure.(none) +4 -0
Bug#26977 exception handlers never hreturn
- In some cases, flow control optimization implemented in sp::optimize
removes hreturn instructions, causing SQL exception handlers to:
* never return
* execute wrong logic
- This patch overrides default short cut optimization on hreturn instructions
to avoid this problem.
mysql-test/r/sp-code.result@stripped, 2007-05-02 14:25:00+02:00, thek@adventure.(none) +113 -0
Added test case
mysql-test/t/sp-code.test@stripped, 2007-05-02 14:25:00+02:00, thek@adventure.(none) +75 -0
Added test case
sql/sp_head.cc@stripped, 2007-05-02 14:25:00+02:00, thek@adventure.(none) +13 -3
Override opt_mark to get correct execution paths without jump short cut
optimization.
sql/sp_head.h@stripped, 2007-05-02 14:25:00+02:00, thek@adventure.(none) +6 -0
Added override sp_instr_hreturn::opt_shortcut_jump so that jump short cuts aren't
performed on hreturn instructions operating on handlers which are set to CONTINUE
after interruption.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: thek
# Host: adventure.(none)
# Root: /home/thek/Development/cpp/bug26977/my50-bug26977
--- 1.10/mysql-test/r/sp-code.result 2007-03-27 18:31:42 +02:00
+++ 1.11/mysql-test/r/sp-code.result 2007-05-02 14:25:00 +02:00
@@ -620,4 +620,117 @@ SHOW PROCEDURE CODE p1;
Pos Instruction
0 stmt 2 "CREATE INDEX idx ON t1 (c1)"
DROP PROCEDURE p1;
+drop table if exists t1;
+drop procedure if exists proc_broken;
+drop procedure if exists proc_works;
+create table t1(a int unique);
+create procedure proc_broken(v int)
+begin
+declare i int default 5;
+declare continue handler for sqlexception
+begin
+select 'caught something';
+retry:
+while i > 0 do
+begin
+set i = i - 1;
+select 'looping', i;
+end;
+end while retry;
+end;
+select 'do something';
+insert into t1 values (v);
+select 'do something again';
+insert into t1 values (v);
+end//
+create procedure proc_works(v int)
+begin
+declare i int default 5;
+declare continue handler for sqlexception
+begin
+select 'caught something';
+retry:
+while i > 0 do
+begin
+set i = i - 1;
+select 'looping', i;
+end;
+end while retry;
+select 'optimizer: keep hreturn';
+end;
+select 'do something';
+insert into t1 values (v);
+select 'do something again';
+insert into t1 values (v);
+end//
+show procedure code proc_broken;
+Pos Instruction
+0 set i@1 5
+1 hpush_jump 8 2 CONTINUE
+2 stmt 0 "select 'caught something'"
+3 jump_if_not 7(7) (i@1 > 0)
+4 set i@1 (i@1 - 1)
+5 stmt 0 "select 'looping', i"
+6 jump 3
+7 hreturn 2
+8 stmt 0 "select 'do something'"
+9 stmt 5 "insert into t1 values (v)"
+10 stmt 0 "select 'do something again'"
+11 stmt 5 "insert into t1 values (v)"
+12 hpop 1
+show procedure code proc_works;
+Pos Instruction
+0 set i@1 5
+1 hpush_jump 9 2 CONTINUE
+2 stmt 0 "select 'caught something'"
+3 jump_if_not 7(7) (i@1 > 0)
+4 set i@1 (i@1 - 1)
+5 stmt 0 "select 'looping', i"
+6 jump 3
+7 stmt 0 "select 'optimizer: keep hreturn'"
+8 hreturn 2
+9 stmt 0 "select 'do something'"
+10 stmt 5 "insert into t1 values (v)"
+11 stmt 0 "select 'do something again'"
+12 stmt 5 "insert into t1 values (v)"
+13 hpop 1
+call proc_broken(1);
+do something
+do something
+do something again
+do something again
+caught something
+caught something
+looping i
+looping 4
+looping i
+looping 3
+looping i
+looping 2
+looping i
+looping 1
+looping i
+looping 0
+call proc_works(2);
+do something
+do something
+do something again
+do something again
+caught something
+caught something
+looping i
+looping 4
+looping i
+looping 3
+looping i
+looping 2
+looping i
+looping 1
+looping i
+looping 0
+optimizer: keep hreturn
+optimizer: keep hreturn
+drop table t1;
+drop procedure proc_broken;
+drop procedure proc_works;
End of 5.0 tests.
--- 1.6/mysql-test/t/sp-code.test 2006-11-17 20:14:27 +01:00
+++ 1.7/mysql-test/t/sp-code.test 2007-05-02 14:25:00 +02:00
@@ -446,4 +446,79 @@ SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1;
+#
+# Bug#26977 exception handlers never hreturn
+#
+--disable_warnings
+drop table if exists t1;
+drop procedure if exists proc_broken;
+drop procedure if exists proc_works;
+--enable_warnings
+
+create table t1(a int unique);
+
+delimiter //;
+
+create procedure proc_broken(v int)
+begin
+ declare i int default 5;
+
+ declare continue handler for sqlexception
+ begin
+ select 'caught something';
+ retry:
+ while i > 0 do
+ begin
+ set i = i - 1;
+ select 'looping', i;
+ end;
+ end while retry;
+ end;
+
+ select 'do something';
+ insert into t1 values (v);
+ select 'do something again';
+ insert into t1 values (v);
+end//
+
+create procedure proc_works(v int)
+begin
+ declare i int default 5;
+
+ declare continue handler for sqlexception
+ begin
+ select 'caught something';
+ retry:
+ while i > 0 do
+ begin
+ set i = i - 1;
+ select 'looping', i;
+ end;
+ end while retry;
+ select 'optimizer: keep hreturn';
+ end;
+
+ select 'do something';
+ insert into t1 values (v);
+ select 'do something again';
+ insert into t1 values (v);
+end//
+delimiter ;//
+
+show procedure code proc_broken;
+
+show procedure code proc_works;
+
+## This caust an error because of jump short cut
+## optimization.
+call proc_broken(1);
+
+## This works
+call proc_works(2);
+
+drop table t1;
+drop procedure proc_broken;
+drop procedure proc_works;
+
+
--echo End of 5.0 tests.
--- 1.243/sql/sp_head.cc 2007-04-24 17:25:50 +02:00
+++ 1.244/sql/sp_head.cc 2007-05-02 14:25:00 +02:00
@@ -2982,10 +2982,20 @@ sp_instr_hreturn::print(String *str)
uint
sp_instr_hreturn::opt_mark(sp_head *sp, List<sp_instr> *leads)
{
- if (m_dest)
- return sp_instr_jump::opt_mark(sp, leads);
-
marked= 1;
+
+ if (m_dest)
+ {
+ /*
+ * This is an EXIT handler; next instruction step is in m_dest.
+ */
+ return m_dest;
+ }
+
+ /*
+ * This is a CONTINUE handler; next instruction step will come from
+ * the handler stack and not from opt_mark.
+ */
return UINT_MAX;
}
--- 1.97/sql/sp_head.h 2007-04-24 17:24:18 +02:00
+++ 1.98/sql/sp_head.h 2007-05-02 14:25:00 +02:00
@@ -973,6 +973,12 @@ public:
virtual void print(String *str);
+ /* This instruction will not be short cut optimized. */
+ virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
+ {
+ return m_ip;
+ }
+
virtual uint opt_mark(sp_head *sp, List<sp_instr> *leads);
private:
| Thread |
|---|
| • bk commit into 5.0 tree (thek:1.2440) BUG#26977 | kpettersson | 2 May |