SET sql_mode=ORACLE; # # Testing exceptions in the top-level blocks # # No HANDLER declarations, no exceptions CREATE FUNCTION f1 RETURN INT AS BEGIN RETURN 10; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 freturn 3 10 SELECT f1(); f1() 10 DROP FUNCTION f1; # No HANDLER declarations, no code, no exceptions CREATE PROCEDURE p1 () IS BEGIN END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 jump 2 CALL p1; DROP PROCEDURE p1; # No HANDLER declarations, no code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN EXCEPTION WHEN 1002 THEN v:=225; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 jump 1 1 hpush_jump 4 1 EXIT 2 set v@0 225 3 hreturn 0 4 4 hpop 1 set @v= 10; CALL p1(@v); SELECT @v; @v 10 DROP PROCEDURE p1; # No HANDLER declarations, some code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=224; EXCEPTION WHEN 1002 THEN v:=225; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 jump 3 1 set v@0 224 2 jump 6 3 hpush_jump 1 1 EXIT 4 set v@0 225 5 hreturn 0 6 6 hpop 1 set @v= 10; CALL p1(@v); SELECT @v; @v 224 DROP PROCEDURE p1; # Some HANDLER declarations, no code, no exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS EXIT HANDLER FOR 1000 BEGIN v:=123; END; BEGIN END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 hpush_jump 3 1 EXIT 1 set v@0 123 2 hreturn 0 3 3 hpop 1 set @v= 10; CALL p1(@v); SELECT @v; @v 10 DROP PROCEDURE p1; # Some HANDLER declarations, no code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS EXIT HANDLER FOR 1000 BEGIN v:=123; END; BEGIN EXCEPTION WHEN 1002 THEN v:=225; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 hpush_jump 3 1 EXIT 1 set v@0 123 2 hreturn 0 6 3 hpush_jump 6 1 EXIT 4 set v@0 225 5 hreturn 0 6 6 hpop 2 set @v= 10; CALL p1(@v); SELECT @v; @v 10 DROP PROCEDURE p1; # Some HANDLER declarations, some code, no exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS EXIT HANDLER FOR 1000 BEGIN v:=123; END; BEGIN v:=223; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 hpush_jump 3 1 EXIT 1 set v@0 123 2 hreturn 0 4 3 set v@0 223 4 hpop 1 set @v= 10; CALL p1(@v); SELECT @v; @v 223 DROP PROCEDURE p1; # Some HANDLER declarations, some code, some exceptions CREATE PROCEDURE p1 (v IN OUT VARCHAR2(20)) IS EXIT HANDLER FOR 1000 BEGIN v:=123; END; CONTINUE HANDLER FOR 1001 BEGIN SET v=223; END; BEGIN v:= 1; EXCEPTION WHEN 1002 THEN SET v=225; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 hpush_jump 3 1 EXIT 1 set v@0 123 2 hreturn 0 12 3 hpush_jump 8 1 CONTINUE 4 set v@0 223 5 hreturn 1 6 set v@0 1 7 jump 12 8 hpush_jump 6 1 EXIT 9 set v@0 225 10 hreturn 0 12 11 jump 6 12 hpop 3 DROP PROCEDURE p1; # # Testing EXCEPTIONS in internal blocks # # No HANDLER declarations, no code, no exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; BEGIN END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 jump 5 SET @v=10; CALL p1(@v); SELECT @v; @v 123 DROP PROCEDURE p1; # No HANDLER declarations, no code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; BEGIN EXCEPTION WHEN 20002 THEN v:=335; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 jump 2 2 hpush_jump 5 1 EXIT 3 set v@0 335 4 hreturn 0 5 5 hpop 1 SET @v=10; CALL p1(@v); SELECT @v; @v 123 DROP PROCEDURE p1; # No HANDLER declarations, some code, no exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; BEGIN v:=223; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 set v@0 223 2 jump 6 SET @v=10; CALL p1(@v); SELECT @v; @v 223 DROP PROCEDURE p1; # No HANDLER declarations, some code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; BEGIN v:=223; EXCEPTION WHEN 20002 THEN v:=335; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 jump 4 2 set v@0 223 3 jump 7 4 hpush_jump 2 1 EXIT 5 set v@0 335 6 hreturn 0 7 7 hpop 1 SET @v=10; CALL p1(@v); SELECT @v; @v 223 DROP PROCEDURE p1; # Some HANDLER declarations, no code, no exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; DECLARE EXIT HANDLER FOR 1000 BEGIN v:=323; END; BEGIN END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 hpush_jump 4 1 EXIT 2 set v@0 323 3 hreturn 0 4 4 hpop 1 SET @v=10; CALL p1(@v); SELECT @v; @v 123 DROP PROCEDURE p1; # Some HANDLER declarations, no code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; DECLARE EXIT HANDLER FOR 1000 BEGIN v:=323; END; BEGIN EXCEPTION WHEN 20002 THEN v:=335; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 hpush_jump 4 1 EXIT 2 set v@0 323 3 hreturn 0 7 4 hpush_jump 7 1 EXIT 5 set v@0 335 6 hreturn 0 7 7 hpop 2 SET @v=10; CALL p1(@v); SELECT @v; @v 123 DROP PROCEDURE p1; # Some HANDLER declarations, some code, no exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; DECLARE EXIT HANDLER FOR 1000 BEGIN v:=323; END; BEGIN v:= 324; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 hpush_jump 4 1 EXIT 2 set v@0 323 3 hreturn 0 5 4 set v@0 324 5 hpop 1 SET @v=10; CALL p1(@v); SELECT @v; @v 324 DROP PROCEDURE p1; # Some HANDLER declarations, some code, some exceptions CREATE PROCEDURE p1 (v IN OUT INT) IS BEGIN v:=123; DECLARE EXIT HANDLER FOR 1000 BEGIN v:=323; END; BEGIN v:= 324; EXCEPTION WHEN 2002 THEN v:= 325; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set v@0 123 1 hpush_jump 6 1 EXIT 2 set v@0 323 3 hreturn 0 9 4 set v@0 324 5 jump 9 6 hpush_jump 4 1 EXIT 7 set v@0 325 8 hreturn 0 9 9 hpop 2 SET @v=10; CALL p1(@v); SELECT @v; @v 324 DROP PROCEDURE p1; # # Testing EXIT statement # CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN LOOP i:= i + 1; IF i >= 5 THEN EXIT; END IF; END LOOP; RETURN i; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set i@0 0 1 set i@0 i@0 + 1 2 jump_if_not 1(1) i@0 >= 5 3 jump 4 4 freturn 3 i@0 SELECT f1() FROM DUAL; f1() 5 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN LOOP i:= i + 1; EXIT WHEN i >=5; END LOOP; RETURN i; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set i@0 0 1 set i@0 i@0 + 1 2 jump_if_not 1(0) i@0 >= 5 3 jump 4 4 freturn 3 i@0 SELECT f1() FROM DUAL; f1() 5 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN LOOP BEGIN i:= i + 1; IF i >= 5 THEN EXIT; END IF; EXCEPTION WHEN OTHERS THEN i:= 1000; END; END LOOP; RETURN i; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set i@0 0 1 jump 5 2 set i@0 i@0 + 1 3 jump_if_not 8(8) i@0 >= 5 4 jump 10 5 hpush_jump 2 1 EXIT 6 set i@0 1000 7 hreturn 0 8 8 hpop 1 9 jump 5 10 freturn 3 i@0 SELECT f1() FROM DUAL; f1() 5 DROP FUNCTION f1; CREATE PROCEDURE p1(a IN OUT INT) IS i INT := 0; BEGIN LOOP LOOP BEGIN i:= i + 1; IF i >=5 THEN EXIT; END IF; EXCEPTION WHEN OTHERS THEN a:=1000; END; END LOOP; i:= i + 100; EXIT; END LOOP; a:= i; EXCEPTION WHEN OTHERS THEN a:=11; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 set i@1 0 1 jump 14 2 set i@1 i@1 + 1 3 jump_if_not 8(8) i@1 >= 5 4 jump 10 5 hpush_jump 2 2 EXIT 6 set a@0 1000 7 hreturn 0 8 8 hpop 1 9 jump 5 10 set i@1 i@1 + 100 11 jump 12 12 set a@0 i@1 13 jump 17 14 hpush_jump 5 2 EXIT 15 set a@0 11 16 hreturn 0 17 17 hpop 1 set @v= 10; CALL p1(@v); SELECT @v; @v 105 DROP PROCEDURE p1; # Testing RETURN in procedures CREATE PROCEDURE p1 (a IN OUT INT) AS BEGIN IF a < 10 THEN BEGIN a:= a + 1; RETURN; END; END IF; a:= 200; EXCEPTION WHEN OTHERS THEN BEGIN a:= 100; RETURN; END; END; / SHOW PROCEDURE CODE p1; Pos Instruction 0 jump 6 1 jump_if_not 4(4) a@0 < 10 2 set a@0 a@0 + 1 3 preturn 4 set a@0 200 5 jump 9 6 hpush_jump 1 1 EXIT 7 set a@0 100 8 preturn 9 hpop 1 DROP PROCEDURE p1; # Testing FOR loop statement CREATE FUNCTION f1 (a INT, b INT) RETURN INT AS total INT := 0; BEGIN FOR i IN 1 .. a LOOP total:= total + i; IF i = b THEN EXIT; END IF; END LOOP; RETURN total; END / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@2 0 1 set i@3 1 2 set [upper_bound]@4 a@0 3 jump_if_not 9(9) i@3 <= [upper_bound]@4 4 set total@2 total@2 + i@3 5 jump_if_not 7(7) i@3 = b@1 6 jump 9 7 set i@3 i@3 + 1 8 jump 3 9 freturn 3 total@2 SELECT f1(3, 100) FROM DUAL; f1(3, 100) 6 SELECT f1(3, 2) FROM DUAL; f1(3, 2) 3 DROP FUNCTION f1; CREATE FUNCTION f1 (a INT, b INT) RETURN INT AS total INT := 0; BEGIN FOR i IN REVERSE a..1 LOOP total:= total + i; IF i = b THEN EXIT; END IF; END LOOP; RETURN total; END / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@2 0 1 set i@3 a@0 2 set [upper_bound]@4 1 3 jump_if_not 9(9) i@3 >= [upper_bound]@4 4 set total@2 total@2 + i@3 5 jump_if_not 7(7) i@3 = b@1 6 jump 9 7 set i@3 i@3 + -1 8 jump 3 9 freturn 3 total@2 SELECT f1(3, 100) FROM DUAL; f1(3, 100) 6 SELECT f1(3, 2) FROM DUAL; f1(3, 2) 5 DROP FUNCTION f1; # Testing labeled FOR LOOP statement CREATE FUNCTION f1 (a INT, limita INT, b INT, limitb INT) RETURN INT AS total INT := 0; BEGIN <> FOR ia IN 1 .. a LOOP total:= total + 1000; <> FOR ib IN 1 .. b LOOP total:= total + 1; EXIT lb WHEN ib = limitb; EXIT la WHEN ia = limita; END LOOP lb; END LOOP la; RETURN total; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@4 0 1 set ia@5 1 2 set [upper_bound]@6 a@0 3 jump_if_not 17(17) ia@5 <= [upper_bound]@6 4 set total@4 total@4 + 1000 5 set ib@7 1 6 set [upper_bound]@8 b@2 7 jump_if_not 15(15) ib@7 <= [upper_bound]@8 8 set total@4 total@4 + 1 9 jump_if_not 11(0) ib@7 = limitb@3 10 jump 15 11 jump_if_not 13(0) ia@5 = limita@1 12 jump 17 13 set ib@7 ib@7 + 1 14 jump 7 15 set ia@5 ia@5 + 1 16 jump 3 17 freturn 3 total@4 SELECT f1(2, 1, 2, 2) FROM DUAL; f1(2, 1, 2, 2) 1001 SELECT f1(2, 2, 2, 2) FROM DUAL; f1(2, 2, 2, 2) 2003 SELECT f1(2, 3, 2, 3) FROM DUAL; f1(2, 3, 2, 3) 2004 DROP FUNCTION f1; # Testing labeled ITERATE in a labeled FOR LOOP CREATE FUNCTION f1(a INT) RETURN INT AS total INT:= 0; BEGIN <
  • > FOR i IN 1 .. a LOOP total:= total + 1000; IF i = 5 THEN ITERATE li; END IF; total:= total + 1; END LOOP; RETURN total; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@1 0 1 set i@2 1 2 set [upper_bound]@3 a@0 3 jump_if_not 11(11) i@2 <= [upper_bound]@3 4 set total@1 total@1 + 1000 5 jump_if_not 8(8) i@2 = 5 6 set i@2 i@2 + 1 7 jump 3 8 set total@1 total@1 + 1 9 set i@2 i@2 + 1 10 jump 3 11 freturn 3 total@1 SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL; f1(3) f1(4) f1(5) f1(6) 3003 4004 5004 6005 DROP FUNCTION f1; CREATE FUNCTION f1(a INT) RETURN INT AS total INT:= 0; BEGIN <
  • > FOR i IN 1 .. a LOOP FOR j IN 1 .. 2 LOOP total:= total + 1000; IF i = 5 THEN ITERATE li; END IF; total:= total + 1; END LOOP; END LOOP; RETURN total; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@1 0 1 set i@2 1 2 set [upper_bound]@3 a@0 3 jump_if_not 16(16) i@2 <= [upper_bound]@3 4 set j@4 1 5 set [upper_bound]@5 2 6 jump_if_not 14(14) j@4 <= [upper_bound]@5 7 set total@1 total@1 + 1000 8 jump_if_not 11(11) i@2 = 5 9 set i@2 i@2 + 1 10 jump 3 11 set total@1 total@1 + 1 12 set j@4 j@4 + 1 13 jump 6 14 set i@2 i@2 + 1 15 jump 3 16 freturn 3 total@1 SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL; f1(3) f1(4) f1(5) f1(6) 6006 8008 9008 11010 DROP FUNCTION f1; CREATE FUNCTION f1(a INT) RETURN INT AS total INT:= 0; BEGIN <> FOR j IN 1 .. 2 LOOP <
  • > FOR i IN 1 .. a LOOP total:= total + 1000; IF i = 5 THEN ITERATE li; END IF; total:= total + 1; END LOOP; END LOOP; RETURN total; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@1 0 1 set j@2 1 2 set [upper_bound]@3 2 3 jump_if_not 16(16) j@2 <= [upper_bound]@3 4 set i@4 1 5 set [upper_bound]@5 a@0 6 jump_if_not 14(14) i@4 <= [upper_bound]@5 7 set total@1 total@1 + 1000 8 jump_if_not 11(11) i@4 = 5 9 set i@4 i@4 + 1 10 jump 6 11 set total@1 total@1 + 1 12 set i@4 i@4 + 1 13 jump 6 14 set j@2 j@2 + 1 15 jump 3 16 freturn 3 total@1 SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL; f1(3) f1(4) f1(5) f1(6) 6006 8008 10008 12010 DROP FUNCTION f1; # Testing CONTINUE statement CREATE FUNCTION f1(a INT) RETURN INT AS total INT:= 0; BEGIN FOR i IN 1 .. a LOOP CONTINUE WHEN i=5; total:= total + 1; END LOOP; RETURN total; END; / SHOW FUNCTION CODE f1; Pos Instruction 0 set total@1 0 1 set i@2 1 2 set [upper_bound]@3 a@0 3 jump_if_not 10(10) i@2 <= [upper_bound]@3 4 jump_if_not 7(0) i@2 = 5 5 set i@2 i@2 + 1 6 jump 3 7 set total@1 total@1 + 1 8 set i@2 i@2 + 1 9 jump 3 10 freturn 3 total@1 SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL; f1(3) f1(4) f1(5) f1(6) 3 4 4 5 DROP FUNCTION f1;