Skip to content

Commit f9192e6

Browse files
authored
Merge pull request IvorySQL#1125 from rophy/fix/1007
fix: allow COMMIT/ROLLBACK in nested PL/iSQL procedure calls
2 parents f574049 + 39ffc11 commit f9192e6

5 files changed

Lines changed: 375 additions & 2 deletions

File tree

src/oracle_test/regress/expected/ora_package.out

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6278,6 +6278,44 @@ call test_pkg.test_p1(NULL, 23);
62786278
(1 row)
62796279

62806280
DROP package test_pkg;
6281+
-- Test COMMIT in nested package procedure calls (Issue #1007)
6282+
CREATE TABLE test_nested_commit (id int);
6283+
CREATE OR REPLACE PACKAGE pkg_commit_test IS
6284+
PROCEDURE do_commit;
6285+
PROCEDURE main;
6286+
END;
6287+
/
6288+
CREATE OR REPLACE PACKAGE BODY pkg_commit_test IS
6289+
PROCEDURE do_commit IS
6290+
BEGIN
6291+
INSERT INTO test_nested_commit VALUES (1);
6292+
COMMIT;
6293+
INSERT INTO test_nested_commit VALUES (2);
6294+
END;
6295+
PROCEDURE main IS
6296+
BEGIN
6297+
INSERT INTO test_nested_commit VALUES (0);
6298+
do_commit();
6299+
INSERT INTO test_nested_commit VALUES (3);
6300+
END;
6301+
END;
6302+
/
6303+
TRUNCATE test_nested_commit;
6304+
BEGIN
6305+
pkg_commit_test.main();
6306+
END;
6307+
/
6308+
SELECT * FROM test_nested_commit ORDER BY id;
6309+
id
6310+
----
6311+
0
6312+
1
6313+
2
6314+
3
6315+
(4 rows)
6316+
6317+
DROP PACKAGE pkg_commit_test;
6318+
DROP TABLE test_nested_commit;
62816319
--clean data
62826320
RESET ivorysql.allow_out_parameter_const;
62836321
DROP FUNCTION test_event_trigger;

src/oracle_test/regress/sql/ora_package.sql

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6094,6 +6094,42 @@ call test_pkg.test_p1(NULL, 23);
60946094

60956095
DROP package test_pkg;
60966096

6097+
-- Test COMMIT in nested package procedure calls (Issue #1007)
6098+
CREATE TABLE test_nested_commit (id int);
6099+
6100+
CREATE OR REPLACE PACKAGE pkg_commit_test IS
6101+
PROCEDURE do_commit;
6102+
PROCEDURE main;
6103+
END;
6104+
/
6105+
6106+
CREATE OR REPLACE PACKAGE BODY pkg_commit_test IS
6107+
PROCEDURE do_commit IS
6108+
BEGIN
6109+
INSERT INTO test_nested_commit VALUES (1);
6110+
COMMIT;
6111+
INSERT INTO test_nested_commit VALUES (2);
6112+
END;
6113+
6114+
PROCEDURE main IS
6115+
BEGIN
6116+
INSERT INTO test_nested_commit VALUES (0);
6117+
do_commit();
6118+
INSERT INTO test_nested_commit VALUES (3);
6119+
END;
6120+
END;
6121+
/
6122+
6123+
TRUNCATE test_nested_commit;
6124+
BEGIN
6125+
pkg_commit_test.main();
6126+
END;
6127+
/
6128+
SELECT * FROM test_nested_commit ORDER BY id;
6129+
6130+
DROP PACKAGE pkg_commit_test;
6131+
DROP TABLE test_nested_commit;
6132+
60976133
--clean data
60986134
RESET ivorysql.allow_out_parameter_const;
60996135
DROP FUNCTION test_event_trigger;

src/pl/plisql/src/expected/plisql_transaction.out

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ INSERT INTO test4 SELECT repeat('xyzzy', 2000);
472472
-- that will return a still-toasted value
473473
CREATE FUNCTION data_source(i int) RETURNS TEXT LANGUAGE sql
474474
AS 'select f1 from test4' IMMUTABLE;
475+
/
475476
DO $$
476477
declare x text;
477478
begin
@@ -481,9 +482,8 @@ begin
481482
end loop;
482483
raise notice 'length(x) = %', length(x);
483484
end $$;
485+
NOTICE: length(x) = 10000
484486
/
485-
ERROR: invalid transaction termination
486-
CONTEXT: PL/iSQL function inline_code_block line 6 at COMMIT
487487
-- operations on composite types vs. internal transactions
488488
DO LANGUAGE plisql $$
489489
declare
@@ -748,6 +748,162 @@ SELECT * FROM test1;
748748
2 |
749749
(2 rows)
750750

751+
-- Test nested procedure calls with COMMIT/ROLLBACK (Issue #1007)
752+
--
753+
-- Note: Oracle-syntax procedures (CREATE PROCEDURE ... IS) default to
754+
-- AUTHID DEFINER (prosecdef=true), which forces atomic mode and blocks
755+
-- COMMIT/ROLLBACK. Use AUTHID CURRENT_USER to allow transaction control.
756+
-- This matches Oracle behavior where COMMIT is allowed regardless of AUTHID.
757+
-- Tests below verify COMMIT/ROLLBACK in nested procedure calls
758+
-- using AUTHID CURRENT_USER (Oracle-compatible syntax).
759+
-- Without AUTHID CURRENT_USER, Oracle-syntax procedures default to
760+
-- SECURITY DEFINER (prosecdef=true), which forces atomic mode and
761+
-- blocks COMMIT/ROLLBACK. This is a known limitation (see Test 0).
762+
CREATE TABLE test_nested_commit (id int);
763+
-- Inner procedure with COMMIT
764+
CREATE OR REPLACE PROCEDURE nested_inner_commit AUTHID CURRENT_USER IS
765+
BEGIN
766+
INSERT INTO test_nested_commit VALUES (1);
767+
COMMIT;
768+
INSERT INTO test_nested_commit VALUES (2);
769+
END;
770+
/
771+
-- Outer procedure calling inner with CALL keyword
772+
CREATE OR REPLACE PROCEDURE nested_outer_commit AUTHID CURRENT_USER IS
773+
BEGIN
774+
INSERT INTO test_nested_commit VALUES (0);
775+
CALL nested_inner_commit();
776+
INSERT INTO test_nested_commit VALUES (3);
777+
END;
778+
/
779+
-- Test 1: Basic nested call with COMMIT
780+
TRUNCATE test_nested_commit;
781+
CALL nested_outer_commit();
782+
SELECT * FROM test_nested_commit ORDER BY id;
783+
id
784+
----
785+
0
786+
1
787+
2
788+
3
789+
(4 rows)
790+
791+
-- Test 2: Oracle-style call (without CALL keyword) with COMMIT
792+
CREATE OR REPLACE PROCEDURE nested_outer_oracle_style AUTHID CURRENT_USER IS
793+
BEGIN
794+
INSERT INTO test_nested_commit VALUES (10);
795+
nested_inner_commit(); -- Oracle-style call
796+
INSERT INTO test_nested_commit VALUES (13);
797+
END;
798+
/
799+
TRUNCATE test_nested_commit;
800+
CALL nested_outer_oracle_style();
801+
SELECT * FROM test_nested_commit ORDER BY id;
802+
id
803+
----
804+
1
805+
2
806+
10
807+
13
808+
(4 rows)
809+
810+
-- Test 3: Deeply nested Oracle-style calls (4 levels) with COMMIT
811+
CREATE OR REPLACE PROCEDURE nested_level4 AUTHID CURRENT_USER IS
812+
BEGIN
813+
INSERT INTO test_nested_commit VALUES (104);
814+
COMMIT;
815+
INSERT INTO test_nested_commit VALUES (105);
816+
END;
817+
/
818+
CREATE OR REPLACE PROCEDURE nested_level3 AUTHID CURRENT_USER IS
819+
BEGIN
820+
INSERT INTO test_nested_commit VALUES (103);
821+
nested_level4(); -- Oracle-style call
822+
INSERT INTO test_nested_commit VALUES (106);
823+
END;
824+
/
825+
CREATE OR REPLACE PROCEDURE nested_level2 AUTHID CURRENT_USER IS
826+
BEGIN
827+
INSERT INTO test_nested_commit VALUES (102);
828+
nested_level3(); -- Oracle-style call
829+
INSERT INTO test_nested_commit VALUES (107);
830+
END;
831+
/
832+
CREATE OR REPLACE PROCEDURE nested_level1 AUTHID CURRENT_USER IS
833+
BEGIN
834+
INSERT INTO test_nested_commit VALUES (101);
835+
nested_level2(); -- Oracle-style call
836+
INSERT INTO test_nested_commit VALUES (108);
837+
END;
838+
/
839+
TRUNCATE test_nested_commit;
840+
CALL nested_level1();
841+
SELECT * FROM test_nested_commit ORDER BY id;
842+
id
843+
-----
844+
101
845+
102
846+
103
847+
104
848+
105
849+
106
850+
107
851+
108
852+
(8 rows)
853+
854+
-- Test 4: ROLLBACK in nested procedure with CALL keyword
855+
CREATE OR REPLACE PROCEDURE nested_inner_rollback AUTHID CURRENT_USER IS
856+
BEGIN
857+
INSERT INTO test_nested_commit VALUES (201);
858+
ROLLBACK;
859+
INSERT INTO test_nested_commit VALUES (202);
860+
END;
861+
/
862+
CREATE OR REPLACE PROCEDURE nested_outer_rollback AUTHID CURRENT_USER IS
863+
BEGIN
864+
INSERT INTO test_nested_commit VALUES (200);
865+
CALL nested_inner_rollback();
866+
INSERT INTO test_nested_commit VALUES (203);
867+
END;
868+
/
869+
TRUNCATE test_nested_commit;
870+
CALL nested_outer_rollback();
871+
SELECT * FROM test_nested_commit ORDER BY id;
872+
id
873+
-----
874+
202
875+
203
876+
(2 rows)
877+
878+
-- Test 5: Oracle-style call (without CALL keyword) with ROLLBACK
879+
CREATE OR REPLACE PROCEDURE nested_outer_rollback_oracle_style AUTHID CURRENT_USER IS
880+
BEGIN
881+
INSERT INTO test_nested_commit VALUES (300);
882+
nested_inner_rollback(); -- Oracle-style call
883+
INSERT INTO test_nested_commit VALUES (303);
884+
END;
885+
/
886+
TRUNCATE test_nested_commit;
887+
CALL nested_outer_rollback_oracle_style();
888+
SELECT * FROM test_nested_commit ORDER BY id;
889+
id
890+
-----
891+
202
892+
303
893+
(2 rows)
894+
895+
-- Clean up nested commit tests
896+
DROP PROCEDURE nested_inner_commit;
897+
DROP PROCEDURE nested_outer_commit;
898+
DROP PROCEDURE nested_outer_oracle_style;
899+
DROP PROCEDURE nested_level1;
900+
DROP PROCEDURE nested_level2;
901+
DROP PROCEDURE nested_level3;
902+
DROP PROCEDURE nested_level4;
903+
DROP PROCEDURE nested_inner_rollback;
904+
DROP PROCEDURE nested_outer_rollback;
905+
DROP PROCEDURE nested_outer_rollback_oracle_style;
906+
DROP TABLE test_nested_commit;
751907
DROP TABLE test1;
752908
DROP TABLE test2;
753909
DROP TABLE test3;

src/pl/plisql/src/pl_gram.y

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,6 +2737,9 @@ stmt_execsql : K_IMPORT
27372737
new->expr = build_call_expr(T_WORD, @1, &yylval, &yylloc, yyscanner);
27382738
new->is_call = true;
27392739

2740+
/* Remember we may need a procedure resource owner */
2741+
plisql_curr_compile->requires_procedure_resowner = true;
2742+
27402743
$$ = (PLiSQL_stmt *)new;
27412744
}
27422745
else
@@ -2764,6 +2767,9 @@ stmt_execsql : K_IMPORT
27642767
new->expr = build_call_expr(T_CWORD, @1, &yylval, &yylloc, yyscanner);
27652768
new->is_call = true;
27662769

2770+
/* Remember we may need a procedure resource owner */
2771+
plisql_curr_compile->requires_procedure_resowner = true;
2772+
27672773
$$ = (PLiSQL_stmt *)new;
27682774
}
27692775
else

0 commit comments

Comments
 (0)