List:Commits« Previous MessageNext Message »
From:kpettersson Date:May 7 2007 8:23am
Subject:bk commit into 5.0 tree (thek:1.2440) BUG#26977
View as plain text  
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-07 10:23:10+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-07 10:23:08+02:00, thek@adventure.(none) +113 -0
    Added test case

  mysql-test/t/sp-code.test@stripped, 2007-05-07 10:23:09+02:00, thek@adventure.(none) +75 -0
    Added test case

  sql/sp_head.cc@stripped, 2007-05-07 10:23:09+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-07 10:23:09+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-07 10:23:08 +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_26977_broken;
+drop procedure if exists proc_26977_works;
+create table t1(a int unique);
+create procedure proc_26977_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_26977_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_26977_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_26977_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_26977_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_26977_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_26977_broken;
+drop procedure proc_26977_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-07 10:23:09 +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_26977_broken;
+drop procedure if exists proc_26977_works;
+--enable_warnings
+
+create table t1(a int unique);
+
+delimiter //;
+
+create procedure proc_26977_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_26977_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_26977_broken;
+
+show procedure code proc_26977_works;
+
+## This caust an error because of jump short cut
+## optimization.
+call proc_26977_broken(1);
+
+## This works
+call proc_26977_works(2);
+
+drop table t1;
+drop procedure proc_26977_broken;
+drop procedure proc_26977_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-07 10:23:09 +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-07 10:23:09 +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#26977kpettersson7 May