mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	******
This patch fixes the following bugs:
  - Bug#5889: Exit handler for a warning doesn't hide the warning in
    trigger
  - Bug#9857: Stored procedures: handler for sqlwarning ignored
  - Bug#23032: Handlers declared in a SP do not handle warnings generated
    in sub-SP
  - Bug#36185: Incorrect precedence for warning and exception handlers
The problem was in the way warnings/errors during stored routine execution
were handled. Prior to this patch the logic was as follows:
  - when a warning/an error happens: if we're executing a stored routine,
    and there is a handler for that warning/error, remember the handler,
    ignore the warning/error and continue execution.
  - after a stored routine instruction is executed: check for a remembered
    handler and activate one (if any).
This logic caused several problems:
  - if one instruction generates several warnings (errors) it's impossible
    to choose the right handler -- a handler for the first generated
    condition was chosen and remembered for activation.
  - mess with handling conditions in scopes different from the current one.
  - not putting generated warnings/errors into Warning Info (Diagnostic
    Area) is against The Standard.
The patch changes the logic as follows:
  - Diagnostic Area is cleared on the beginning of each statement that
    either is able to generate warnings, or is able to work with tables.
  - at the end of a stored routine instruction, Diagnostic Area is left
    intact.
  - Diagnostic Area is checked after each stored routine instruction. If
    an instruction generates several condition, it's now possible to take a
    look at all of them and determine an appropriate handler.
		
	
		
			
				
	
	
		
			705 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			705 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#
 | 
						|
# Test the debugging feature "show procedure/function code <name>" 
 | 
						|
#
 | 
						|
 | 
						|
-- source include/have_debug.inc
 | 
						|
 | 
						|
--disable_warnings
 | 
						|
drop procedure if exists empty;
 | 
						|
drop procedure if exists code_sample;
 | 
						|
--enable_warnings
 | 
						|
 | 
						|
create procedure empty()
 | 
						|
begin
 | 
						|
end;
 | 
						|
show procedure code empty;
 | 
						|
drop procedure empty;
 | 
						|
 | 
						|
create function almost_empty()
 | 
						|
    returns int
 | 
						|
  return 0;
 | 
						|
show function code almost_empty;
 | 
						|
drop function almost_empty;
 | 
						|
 | 
						|
delimiter //;
 | 
						|
create procedure code_sample(x int, out err int, out nulls int)
 | 
						|
begin
 | 
						|
  declare count int default 0;
 | 
						|
 | 
						|
  set nulls = 0;
 | 
						|
  begin
 | 
						|
    declare c cursor for select name from t1;
 | 
						|
    declare exit handler for not found close c;
 | 
						|
 | 
						|
    open c;
 | 
						|
    loop
 | 
						|
      begin
 | 
						|
        declare n varchar(20);
 | 
						|
        declare continue handler for sqlexception set err=1;
 | 
						|
 | 
						|
        fetch c into n;
 | 
						|
        if isnull(n) then
 | 
						|
          set nulls = nulls + 1;
 | 
						|
	else
 | 
						|
          set count = count + 1;
 | 
						|
          update t2 set idx = count where name=n;
 | 
						|
        end if;
 | 
						|
      end;
 | 
						|
    end loop;
 | 
						|
  end;
 | 
						|
  select t.name, t.idx from t2 t order by idx asc;
 | 
						|
end//
 | 
						|
delimiter ;//
 | 
						|
show procedure code code_sample;
 | 
						|
drop procedure code_sample;
 | 
						|
 | 
						|
 | 
						|
#
 | 
						|
# BUG#15737: Stored procedure optimizer bug with LEAVE
 | 
						|
#
 | 
						|
# This is a much more extensive test case than is strictly needed,
 | 
						|
# but it was kept as is for two reasons:
 | 
						|
# - The bug occurs under some quite special circumstances, so it
 | 
						|
#   wasn't trivial to create a smaller test,
 | 
						|
# - There's some value in having another more complex code sample
 | 
						|
#   in this test file. This might catch future code generation bugs
 | 
						|
#   that doesn't show in behaviour in any obvious way.
 | 
						|
 | 
						|
--disable_warnings
 | 
						|
drop procedure if exists sudoku_solve;
 | 
						|
--enable_warnings
 | 
						|
 | 
						|
delimiter //;
 | 
						|
create procedure sudoku_solve(p_naive boolean, p_all boolean)
 | 
						|
  deterministic
 | 
						|
  modifies sql data
 | 
						|
begin
 | 
						|
  drop temporary table if exists sudoku_work, sudoku_schedule;
 | 
						|
 | 
						|
  create temporary table sudoku_work
 | 
						|
  (
 | 
						|
    row smallint not null,
 | 
						|
    col smallint not null,
 | 
						|
    dig smallint not null,
 | 
						|
    cnt smallint,
 | 
						|
    key using btree (cnt),
 | 
						|
    key using btree (row),
 | 
						|
    key using btree (col),
 | 
						|
    unique key using hash (row,col)
 | 
						|
  );
 | 
						|
 | 
						|
  create temporary table sudoku_schedule
 | 
						|
  (
 | 
						|
    idx int not null auto_increment primary key,
 | 
						|
    row smallint not null,
 | 
						|
    col smallint not null
 | 
						|
  );
 | 
						|
 | 
						|
  call sudoku_init();
 | 
						|
 | 
						|
  if p_naive then
 | 
						|
    update sudoku_work set cnt = 0 where dig = 0;
 | 
						|
  else
 | 
						|
    call sudoku_count();
 | 
						|
  end if;
 | 
						|
  insert into sudoku_schedule (row,col)
 | 
						|
    select row,col from sudoku_work where cnt is not null order by cnt desc;
 | 
						|
 | 
						|
  begin
 | 
						|
    declare v_scounter bigint default 0;
 | 
						|
    declare v_i smallint default 1;
 | 
						|
    declare v_dig smallint;
 | 
						|
    declare v_schedmax smallint;
 | 
						|
 | 
						|
    select count(*) into v_schedmax from sudoku_schedule;
 | 
						|
 | 
						|
   more: 
 | 
						|
    loop
 | 
						|
    begin
 | 
						|
      declare v_tcounter bigint default 0;
 | 
						|
 | 
						|
     sched:
 | 
						|
      while v_i <= v_schedmax do
 | 
						|
      begin
 | 
						|
        declare v_row, v_col smallint;
 | 
						|
 | 
						|
        select row,col into v_row,v_col from sudoku_schedule where v_i = idx;
 | 
						|
 | 
						|
        select dig into v_dig from sudoku_work
 | 
						|
          where v_row = row and v_col = col;
 | 
						|
 | 
						|
        case v_dig
 | 
						|
        when 0 then
 | 
						|
          set v_dig = 1;
 | 
						|
          update sudoku_work set dig = 1
 | 
						|
            where v_row = row and v_col = col;
 | 
						|
        when 9 then
 | 
						|
          if v_i > 0 then
 | 
						|
            update sudoku_work set dig = 0
 | 
						|
              where v_row = row and v_col = col;
 | 
						|
            set v_i = v_i - 1;
 | 
						|
            iterate sched;
 | 
						|
          else
 | 
						|
            select v_scounter as 'Solutions';
 | 
						|
            leave more;
 | 
						|
          end if;
 | 
						|
        else
 | 
						|
          set v_dig = v_dig + 1;
 | 
						|
          update sudoku_work set dig = v_dig
 | 
						|
            where v_row = row and v_col = col;
 | 
						|
        end case;
 | 
						|
 | 
						|
        set v_tcounter = v_tcounter + 1;
 | 
						|
        if not sudoku_digit_ok(v_row, v_col, v_dig) then
 | 
						|
          iterate sched;
 | 
						|
        end if;
 | 
						|
        set v_i = v_i + 1;
 | 
						|
      end;
 | 
						|
      end while sched;
 | 
						|
 | 
						|
      select dig from sudoku_work;
 | 
						|
      select v_tcounter as 'Tests';
 | 
						|
      set v_scounter = v_scounter + 1;
 | 
						|
 | 
						|
      if p_all and v_i > 0 then
 | 
						|
        set v_i = v_i - 1;
 | 
						|
      else
 | 
						|
        leave more;
 | 
						|
      end if;
 | 
						|
    end;
 | 
						|
    end loop more;
 | 
						|
  end;
 | 
						|
 | 
						|
  drop temporary table sudoku_work, sudoku_schedule;
 | 
						|
end//
 | 
						|
delimiter ;//
 | 
						|
 | 
						|
# The interestings parts are where the code for the two "leave" are:
 | 
						|
# ...
 | 
						|
#|  26 | jump_if_not 30 (v_i@3 > 0)                                            |
 | 
						|
# ...
 | 
						|
#|  30 | stmt 0 "select v_scounter as 'Solutions'"                             |
 | 
						|
#|  31 | jump 45                                                               |
 | 
						|
# ...
 | 
						|
#|  42 | jump_if_not 45 (p_all@1 and (v_i@3 > 0))                              |
 | 
						|
#|  43 | set v_i@3 (v_i@3 - 1)                                                 |
 | 
						|
#|  44 | jump 14                                                               |
 | 
						|
#|  45 | stmt 9 "drop temporary table sudoku_work, sud..."                     |
 | 
						|
#+-----+-----------------------------------------------------------------------+
 | 
						|
# The bug appeared at position 42 (with the wrong destination).
 | 
						|
show procedure code sudoku_solve;
 | 
						|
 | 
						|
drop procedure sudoku_solve;
 | 
						|
 | 
						|
#
 | 
						|
# Bug#19194 (Right recursion in parser for CASE causes excessive stack
 | 
						|
#   usage, limitation)
 | 
						|
# This bug also exposed a flaw in the generated code with nested case
 | 
						|
# statements
 | 
						|
#
 | 
						|
 | 
						|
--disable_warnings
 | 
						|
DROP PROCEDURE IF EXISTS proc_19194_simple;
 | 
						|
DROP PROCEDURE IF EXISTS proc_19194_searched;
 | 
						|
DROP PROCEDURE IF EXISTS proc_19194_nested_1;
 | 
						|
DROP PROCEDURE IF EXISTS proc_19194_nested_2;
 | 
						|
DROP PROCEDURE IF EXISTS proc_19194_nested_3;
 | 
						|
DROP PROCEDURE IF EXISTS proc_19194_nested_4;
 | 
						|
--enable_warnings
 | 
						|
 | 
						|
delimiter |;
 | 
						|
 | 
						|
CREATE PROCEDURE proc_19194_simple(i int)
 | 
						|
BEGIN
 | 
						|
  DECLARE str CHAR(10);
 | 
						|
 | 
						|
  CASE i
 | 
						|
    WHEN 1 THEN SET str="1";
 | 
						|
    WHEN 2 THEN SET str="2";
 | 
						|
    WHEN 3 THEN SET str="3";
 | 
						|
    ELSE SET str="unknown";
 | 
						|
  END CASE;
 | 
						|
 | 
						|
  SELECT str;
 | 
						|
END|
 | 
						|
 | 
						|
CREATE PROCEDURE proc_19194_searched(i int)
 | 
						|
BEGIN
 | 
						|
  DECLARE str CHAR(10);
 | 
						|
 | 
						|
  CASE
 | 
						|
    WHEN i=1 THEN SET str="1";
 | 
						|
    WHEN i=2 THEN SET str="2";
 | 
						|
    WHEN i=3 THEN SET str="3";
 | 
						|
    ELSE SET str="unknown";
 | 
						|
  END CASE;
 | 
						|
 | 
						|
  SELECT str;
 | 
						|
END|
 | 
						|
 | 
						|
# Outer SIMPLE case, inner SEARCHED case
 | 
						|
CREATE PROCEDURE proc_19194_nested_1(i int, j int)
 | 
						|
BEGIN
 | 
						|
  DECLARE str_i CHAR(10);
 | 
						|
  DECLARE str_j CHAR(10);
 | 
						|
 | 
						|
  CASE i
 | 
						|
    WHEN 10 THEN SET str_i="10";
 | 
						|
    WHEN 20 THEN
 | 
						|
    BEGIN
 | 
						|
      set str_i="20";
 | 
						|
      CASE
 | 
						|
        WHEN j=1 THEN SET str_j="1";
 | 
						|
        WHEN j=2 THEN SET str_j="2";
 | 
						|
        WHEN j=3 THEN SET str_j="3";
 | 
						|
      ELSE SET str_j="unknown";
 | 
						|
      END CASE;
 | 
						|
      select "i was 20";
 | 
						|
    END;
 | 
						|
    WHEN 30 THEN SET str_i="30";
 | 
						|
    WHEN 40 THEN SET str_i="40";
 | 
						|
    ELSE SET str_i="unknown";
 | 
						|
  END CASE;
 | 
						|
 | 
						|
  SELECT str_i, str_j;
 | 
						|
END|
 | 
						|
 | 
						|
# Outer SEARCHED case, inner SIMPLE case
 | 
						|
CREATE PROCEDURE proc_19194_nested_2(i int, j int)
 | 
						|
BEGIN
 | 
						|
  DECLARE str_i CHAR(10);
 | 
						|
  DECLARE str_j CHAR(10);
 | 
						|
 | 
						|
  CASE
 | 
						|
    WHEN i=10 THEN SET str_i="10";
 | 
						|
    WHEN i=20 THEN
 | 
						|
    BEGIN
 | 
						|
      set str_i="20";
 | 
						|
      CASE j
 | 
						|
        WHEN 1 THEN SET str_j="1";
 | 
						|
        WHEN 2 THEN SET str_j="2";
 | 
						|
        WHEN 3 THEN SET str_j="3";
 | 
						|
      ELSE SET str_j="unknown";
 | 
						|
      END CASE;
 | 
						|
      select "i was 20";
 | 
						|
    END;
 | 
						|
    WHEN i=30 THEN SET str_i="30";
 | 
						|
    WHEN i=40 THEN SET str_i="40";
 | 
						|
    ELSE SET str_i="unknown";
 | 
						|
  END CASE;
 | 
						|
 | 
						|
  SELECT str_i, str_j;
 | 
						|
END|
 | 
						|
 | 
						|
# Outer SIMPLE case, inner SIMPLE case
 | 
						|
CREATE PROCEDURE proc_19194_nested_3(i int, j int)
 | 
						|
BEGIN
 | 
						|
  DECLARE str_i CHAR(10);
 | 
						|
  DECLARE str_j CHAR(10);
 | 
						|
 | 
						|
  CASE i
 | 
						|
    WHEN 10 THEN SET str_i="10";
 | 
						|
    WHEN 20 THEN
 | 
						|
    BEGIN
 | 
						|
      set str_i="20";
 | 
						|
      CASE j
 | 
						|
        WHEN 1 THEN SET str_j="1";
 | 
						|
        WHEN 2 THEN SET str_j="2";
 | 
						|
        WHEN 3 THEN SET str_j="3";
 | 
						|
      ELSE SET str_j="unknown";
 | 
						|
      END CASE;
 | 
						|
      select "i was 20";
 | 
						|
    END;
 | 
						|
    WHEN 30 THEN SET str_i="30";
 | 
						|
    WHEN 40 THEN SET str_i="40";
 | 
						|
    ELSE SET str_i="unknown";
 | 
						|
  END CASE;
 | 
						|
 | 
						|
  SELECT str_i, str_j;
 | 
						|
END|
 | 
						|
 | 
						|
# Outer SEARCHED case, inner SEARCHED case
 | 
						|
CREATE PROCEDURE proc_19194_nested_4(i int, j int)
 | 
						|
BEGIN
 | 
						|
  DECLARE str_i CHAR(10);
 | 
						|
  DECLARE str_j CHAR(10);
 | 
						|
 | 
						|
  CASE
 | 
						|
    WHEN i=10 THEN SET str_i="10";
 | 
						|
    WHEN i=20 THEN
 | 
						|
    BEGIN
 | 
						|
      set str_i="20";
 | 
						|
      CASE
 | 
						|
        WHEN j=1 THEN SET str_j="1";
 | 
						|
        WHEN j=2 THEN SET str_j="2";
 | 
						|
        WHEN j=3 THEN SET str_j="3";
 | 
						|
      ELSE SET str_j="unknown";
 | 
						|
      END CASE;
 | 
						|
      select "i was 20";
 | 
						|
    END;
 | 
						|
    WHEN i=30 THEN SET str_i="30";
 | 
						|
    WHEN i=40 THEN SET str_i="40";
 | 
						|
    ELSE SET str_i="unknown";
 | 
						|
  END CASE;
 | 
						|
 | 
						|
  SELECT str_i, str_j;
 | 
						|
END|
 | 
						|
 | 
						|
delimiter ;|
 | 
						|
 | 
						|
SHOW PROCEDURE CODE proc_19194_simple;
 | 
						|
SHOW PROCEDURE CODE proc_19194_searched;
 | 
						|
SHOW PROCEDURE CODE proc_19194_nested_1;
 | 
						|
SHOW PROCEDURE CODE proc_19194_nested_2;
 | 
						|
SHOW PROCEDURE CODE proc_19194_nested_3;
 | 
						|
SHOW PROCEDURE CODE proc_19194_nested_4;
 | 
						|
 | 
						|
CALL proc_19194_nested_1(10, 1);
 | 
						|
 | 
						|
#
 | 
						|
# Before 19194, the generated code was:
 | 
						|
#   20      jump_if_not 23(27) 30
 | 
						|
#   21      set str_i@2 _latin1'30'
 | 
						|
# As opposed to the expected:
 | 
						|
#   20      jump_if_not 23(27) (case_expr@0 = 30)
 | 
						|
#   21      set str_i@2 _latin1'30'
 | 
						|
#
 | 
						|
# and as a result, this call returned "30",
 | 
						|
# because the expression 30 is always true,
 | 
						|
# masking the case 40, case 0 and the else.
 | 
						|
#
 | 
						|
CALL proc_19194_nested_1(25, 1);
 | 
						|
 | 
						|
CALL proc_19194_nested_1(20, 1);
 | 
						|
CALL proc_19194_nested_1(20, 2);
 | 
						|
CALL proc_19194_nested_1(20, 3);
 | 
						|
CALL proc_19194_nested_1(20, 4);
 | 
						|
CALL proc_19194_nested_1(30, 1);
 | 
						|
CALL proc_19194_nested_1(40, 1);
 | 
						|
CALL proc_19194_nested_1(0, 0);
 | 
						|
 | 
						|
CALL proc_19194_nested_2(10, 1);
 | 
						|
 | 
						|
#
 | 
						|
# Before 19194, the generated code was:
 | 
						|
#   20      jump_if_not 23(27) (case_expr@0 = (i@0 = 30))
 | 
						|
#   21      set str_i@2 _latin1'30'
 | 
						|
# As opposed to the expected:
 | 
						|
#   20      jump_if_not 23(27) (i@0 = 30)
 | 
						|
#   21      set str_i@2 _latin1'30'
 | 
						|
# and as a result, this call crashed the server, because there is no
 | 
						|
# such variable as "case_expr@0".
 | 
						|
#
 | 
						|
CALL proc_19194_nested_2(25, 1);
 | 
						|
 | 
						|
CALL proc_19194_nested_2(20, 1);
 | 
						|
CALL proc_19194_nested_2(20, 2);
 | 
						|
CALL proc_19194_nested_2(20, 3);
 | 
						|
CALL proc_19194_nested_2(20, 4);
 | 
						|
CALL proc_19194_nested_2(30, 1);
 | 
						|
CALL proc_19194_nested_2(40, 1);
 | 
						|
CALL proc_19194_nested_2(0, 0);
 | 
						|
 | 
						|
CALL proc_19194_nested_3(10, 1);
 | 
						|
CALL proc_19194_nested_3(25, 1);
 | 
						|
CALL proc_19194_nested_3(20, 1);
 | 
						|
CALL proc_19194_nested_3(20, 2);
 | 
						|
CALL proc_19194_nested_3(20, 3);
 | 
						|
CALL proc_19194_nested_3(20, 4);
 | 
						|
CALL proc_19194_nested_3(30, 1);
 | 
						|
CALL proc_19194_nested_3(40, 1);
 | 
						|
CALL proc_19194_nested_3(0, 0);
 | 
						|
 | 
						|
CALL proc_19194_nested_4(10, 1);
 | 
						|
CALL proc_19194_nested_4(25, 1);
 | 
						|
CALL proc_19194_nested_4(20, 1);
 | 
						|
CALL proc_19194_nested_4(20, 2);
 | 
						|
CALL proc_19194_nested_4(20, 3);
 | 
						|
CALL proc_19194_nested_4(20, 4);
 | 
						|
CALL proc_19194_nested_4(30, 1);
 | 
						|
CALL proc_19194_nested_4(40, 1);
 | 
						|
CALL proc_19194_nested_4(0, 0);
 | 
						|
 | 
						|
DROP PROCEDURE proc_19194_simple;
 | 
						|
DROP PROCEDURE proc_19194_searched;
 | 
						|
DROP PROCEDURE proc_19194_nested_1;
 | 
						|
DROP PROCEDURE proc_19194_nested_2;
 | 
						|
DROP PROCEDURE proc_19194_nested_3;
 | 
						|
DROP PROCEDURE proc_19194_nested_4;
 | 
						|
 | 
						|
#
 | 
						|
# Bug#19207: Final parenthesis omitted for CREATE INDEX in Stored
 | 
						|
# Procedure
 | 
						|
#
 | 
						|
# Wrong criteria was used to distinguish the case when there was no
 | 
						|
# lookahead performed in the parser.  Bug affected only statements
 | 
						|
# ending in one-character token without any optional tail, like CREATE
 | 
						|
# INDEX and CALL.
 | 
						|
#
 | 
						|
--disable_warnings
 | 
						|
DROP PROCEDURE IF EXISTS p1;
 | 
						|
--enable_warnings
 | 
						|
 | 
						|
CREATE PROCEDURE p1() CREATE INDEX idx ON t1 (c1);
 | 
						|
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;
 | 
						|
 | 
						|
#
 | 
						|
# Bug#33618 Crash in sp_rcontext
 | 
						|
#
 | 
						|
 | 
						|
--disable_warnings
 | 
						|
drop procedure if exists proc_33618_h;
 | 
						|
drop procedure if exists proc_33618_c;
 | 
						|
--enable_warnings
 | 
						|
 | 
						|
delimiter //;
 | 
						|
 | 
						|
create procedure proc_33618_h(num int)
 | 
						|
begin
 | 
						|
  declare count1 int default '0';
 | 
						|
  declare vb varchar(30);
 | 
						|
  declare last_row int;
 | 
						|
        
 | 
						|
  while(num>=1) do
 | 
						|
    set num=num-1;
 | 
						|
    begin
 | 
						|
      declare cur1 cursor for select `a` from t_33618;
 | 
						|
      declare continue handler for not found set last_row = 1;
 | 
						|
      set last_row:=0;
 | 
						|
      open cur1;
 | 
						|
      rep1:
 | 
						|
      repeat
 | 
						|
        begin
 | 
						|
          declare exit handler for 1062 begin end;
 | 
						|
          fetch cur1 into vb;
 | 
						|
          if (last_row = 1) then
 | 
						|
            ## should generate a hpop instruction here
 | 
						|
            leave rep1;
 | 
						|
          end if;
 | 
						|
        end;
 | 
						|
        until last_row=1
 | 
						|
      end repeat;
 | 
						|
      close cur1;
 | 
						|
    end;
 | 
						|
  end while;
 | 
						|
end//
 | 
						|
 | 
						|
create procedure proc_33618_c(num int)
 | 
						|
begin
 | 
						|
  declare count1 int default '0';
 | 
						|
  declare vb varchar(30);
 | 
						|
  declare last_row int;
 | 
						|
        
 | 
						|
  while(num>=1) do
 | 
						|
    set num=num-1;
 | 
						|
    begin
 | 
						|
      declare cur1 cursor for select `a` from t_33618;
 | 
						|
      declare continue handler for not found set last_row = 1;
 | 
						|
      set last_row:=0;
 | 
						|
      open cur1;
 | 
						|
      rep1:
 | 
						|
      repeat
 | 
						|
        begin
 | 
						|
          declare cur2 cursor for select `b` from t_33618;
 | 
						|
          fetch cur1 into vb;
 | 
						|
          if (last_row = 1) then
 | 
						|
            ## should generate a cpop instruction here
 | 
						|
            leave rep1;
 | 
						|
          end if;
 | 
						|
        end;
 | 
						|
        until last_row=1
 | 
						|
      end repeat;
 | 
						|
      close cur1;
 | 
						|
    end;
 | 
						|
  end while;
 | 
						|
end//
 | 
						|
delimiter ;//
 | 
						|
 | 
						|
show procedure code proc_33618_h;
 | 
						|
show procedure code proc_33618_c;
 | 
						|
 | 
						|
drop procedure proc_33618_h;
 | 
						|
drop procedure proc_33618_c;
 | 
						|
 | 
						|
#
 | 
						|
# Bug#20906 (Multiple assignments in SET in stored routine produce incorrect
 | 
						|
# instructions)
 | 
						|
#
 | 
						|
 | 
						|
--disable_warnings
 | 
						|
drop procedure if exists p_20906_a;
 | 
						|
drop procedure if exists p_20906_b;
 | 
						|
--enable_warnings
 | 
						|
 | 
						|
create procedure p_20906_a() SET @a=@a+1, @b=@b+1;
 | 
						|
show procedure code p_20906_a;
 | 
						|
 | 
						|
set @a=1;
 | 
						|
set @b=1;
 | 
						|
 | 
						|
call p_20906_a();
 | 
						|
select @a, @b;
 | 
						|
 | 
						|
create procedure p_20906_b() SET @a=@a+1, @b=@b+1, @c=@c+1;
 | 
						|
show procedure code p_20906_b;
 | 
						|
 | 
						|
set @a=1;
 | 
						|
set @b=1;
 | 
						|
set @c=1;
 | 
						|
 | 
						|
call p_20906_b();
 | 
						|
select @a, @b, @c;
 | 
						|
 | 
						|
drop procedure p_20906_a;
 | 
						|
drop procedure p_20906_b;
 | 
						|
 | 
						|
--echo End of 5.0 tests.
 | 
						|
 | 
						|
#
 | 
						|
# Bug #26303: reserve() not called before qs_append() may lead to buffer
 | 
						|
# overflow
 | 
						|
#
 | 
						|
DELIMITER //;
 | 
						|
CREATE PROCEDURE p1() 
 | 
						|
BEGIN 
 | 
						|
  DECLARE dummy int default 0;
 | 
						|
 | 
						|
  CASE 12 
 | 
						|
    WHEN 12 
 | 
						|
    THEN SET dummy = 0;
 | 
						|
  END CASE;
 | 
						|
END//
 | 
						|
DELIMITER ;//
 | 
						|
SHOW PROCEDURE CODE p1;
 | 
						|
DROP PROCEDURE p1;
 | 
						|
 | 
						|
--echo #
 | 
						|
--echo # Bug#23032: Handlers declared in a SP do not handle warnings generated in sub-SP
 | 
						|
--echo #
 | 
						|
 | 
						|
--echo
 | 
						|
--echo # - Case 4: check that "No Data trumps Warning".
 | 
						|
--echo
 | 
						|
 | 
						|
CREATE TABLE t1(a INT);
 | 
						|
INSERT INTO t1 VALUES (1), (2), (3);
 | 
						|
 | 
						|
delimiter |;
 | 
						|
 | 
						|
CREATE PROCEDURE p1()
 | 
						|
BEGIN
 | 
						|
  DECLARE c CURSOR FOR SELECT a FROM t1;
 | 
						|
 | 
						|
  OPEN c;
 | 
						|
  
 | 
						|
  BEGIN
 | 
						|
    DECLARE v INT;
 | 
						|
 | 
						|
    DECLARE CONTINUE HANDLER FOR SQLWARNING
 | 
						|
    BEGIN
 | 
						|
      SELECT "Warning found!";
 | 
						|
      SHOW WARNINGS;
 | 
						|
    END;
 | 
						|
 | 
						|
    DECLARE EXIT HANDLER FOR NOT FOUND
 | 
						|
    BEGIN
 | 
						|
      SELECT "End of Result Set found!";
 | 
						|
      SHOW WARNINGS;
 | 
						|
    END;
 | 
						|
 | 
						|
    WHILE TRUE DO
 | 
						|
      FETCH c INTO v;
 | 
						|
    END WHILE;
 | 
						|
  END;
 | 
						|
 | 
						|
  CLOSE c;
 | 
						|
 | 
						|
  SELECT a INTO @foo FROM t1 LIMIT 1; # Clear warning stack
 | 
						|
END|
 | 
						|
 | 
						|
delimiter ;|
 | 
						|
 | 
						|
SET SESSION debug="+d,bug23032_emit_warning";
 | 
						|
CALL p1();
 | 
						|
SET SESSION debug="-d,bug23032_emit_warning";
 | 
						|
 | 
						|
DROP PROCEDURE p1;
 | 
						|
DROP TABLE t1;
 |