diff --git a/mysql-test/suite/compat/oracle/r/sp-code.result b/mysql-test/suite/compat/oracle/r/sp-code.result index 84db01a37bb01..b6d42bfc05b8f 100644 --- a/mysql-test/suite/compat/oracle/r/sp-code.result +++ b/mysql-test/suite/compat/oracle/r/sp-code.result @@ -627,3 +627,53 @@ 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; diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result index ee22dbbb5ec52..ef23f302a3532 100644 --- a/mysql-test/suite/compat/oracle/r/sp.result +++ b/mysql-test/suite/compat/oracle/r/sp.result @@ -860,3 +860,42 @@ 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; +/ +SELECT f1(1, 1, 1, 1) FROM DUAL; +f1(1, 1, 1, 1) +1001 +SELECT f1(1, 2, 1, 2) FROM DUAL; +f1(1, 2, 1, 2) +1001 +SELECT f1(2, 1, 2, 1) FROM DUAL; +f1(2, 1, 2, 1) +2002 +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; diff --git a/mysql-test/suite/compat/oracle/t/sp-code.test b/mysql-test/suite/compat/oracle/t/sp-code.test index a7033f640ff8b..a0ab0e5ab92fc 100644 --- a/mysql-test/suite/compat/oracle/t/sp-code.test +++ b/mysql-test/suite/compat/oracle/t/sp-code.test @@ -485,3 +485,32 @@ SHOW FUNCTION CODE f1; SELECT f1(3, 100) FROM DUAL; SELECT f1(3, 2) FROM DUAL; DROP FUNCTION f1; + +--echo # Testing labeled FOR LOOP statement + +DELIMITER /; +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; +/ +DELIMITER ;/ +SHOW FUNCTION CODE f1; +SELECT f1(2, 1, 2, 2) FROM DUAL; +SELECT f1(2, 2, 2, 2) FROM DUAL; +SELECT f1(2, 3, 2, 3) FROM DUAL; +DROP FUNCTION f1; diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test index bdf12cdbb7d61..3b301f21cea02 100644 --- a/mysql-test/suite/compat/oracle/t/sp.test +++ b/mysql-test/suite/compat/oracle/t/sp.test @@ -931,3 +931,35 @@ DELIMITER ;/ SELECT f1(3, 100) FROM DUAL; SELECT f1(3, 2) FROM DUAL; DROP FUNCTION f1; + + +--echo # Testing labeled FOR LOOP statement + +DELIMITER /; +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; +/ +DELIMITER ;/ +SELECT f1(1, 1, 1, 1) FROM DUAL; +SELECT f1(1, 2, 1, 2) FROM DUAL; +SELECT f1(2, 1, 2, 1) FROM DUAL; +SELECT f1(2, 1, 2, 2) FROM DUAL; +SELECT f1(2, 2, 2, 2) FROM DUAL; +SELECT f1(2, 3, 2, 3) FROM DUAL; +DROP FUNCTION f1; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 863066228aa84..8bdff7b4b5195 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -3575,6 +3575,30 @@ sp_labeled_control: } while_body pop_sp_loop_label { } + | label_declaration_oracle FOR_SYM + { + // See "The FOR LOOP statement" comments in sql_lex.cc + Lex->sp_block_init(thd); // The outer DECLARE..BEGIN..END block + } + sp_for_loop_index_and_bounds + { + if (Lex->sp_push_loop_label(thd, $1)) // The inner WHILE block + MYSQL_YYABORT; + if (Lex->sp_for_loop_index_and_bounds(thd, $4)) + MYSQL_YYABORT; + } + LOOP_SYM + sp_proc_stmts1 + END LOOP_SYM + { + if (Lex->sp_for_loop_finalize(thd, $4)) + MYSQL_YYABORT; + } + pop_sp_loop_label // The inner WHILE block + { + if (Lex->sp_block_finalize(thd)) // The outer DECLARE..BEGIN..END + MYSQL_YYABORT; + } | label_declaration_oracle REPEAT_SYM { if (Lex->sp_push_loop_label(thd, $1))