Skip to content

Commit 307b066

Browse files
committed
fix: allow COMMIT in nested procedure calls for Oracle compatibility
- Make anonymous blocks (DO) and CALL statements non-atomic in Oracle mode - Set requires_procedure_resowner for Oracle-style procedure calls - Update expected test output for plisql_transaction
1 parent 7261f1c commit 307b066

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/backend/tcop/utility.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "utils/acl.h"
6868
#include "utils/guc.h"
6969
#include "utils/lsyscache.h"
70+
#include "utils/ora_compatible.h"
7071

7172
/* Hook for plugins to get control in ProcessUtility() */
7273
ProcessUtility_hook_type ProcessUtility_hook = NULL;
@@ -713,7 +714,25 @@ standard_ProcessUtility(PlannedStmt *pstmt,
713714
break;
714715

715716
case T_DoStmt:
716-
ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext, params, dest);
717+
/*
718+
* In Oracle compatibility mode, anonymous blocks are non-atomic
719+
* by default when executed at the top level or in a non-atomic
720+
* context, allowing COMMIT/ROLLBACK within the block and in
721+
* any procedures called from it. However, if we're already in
722+
* an atomic context (e.g., called from a function), we must
723+
* respect that.
724+
*/
725+
{
726+
bool doAtomicContext = isAtomicContext;
727+
728+
if (compatible_db == ORA_PARSER &&
729+
(context == PROCESS_UTILITY_TOPLEVEL ||
730+
context == PROCESS_UTILITY_QUERY_NONATOMIC))
731+
doAtomicContext = false;
732+
733+
ExecuteDoStmt(pstate, (DoStmt *) parsetree,
734+
doAtomicContext, params, dest);
735+
}
717736
break;
718737

719738
case T_CreateTableSpaceStmt:
@@ -857,7 +876,24 @@ standard_ProcessUtility(PlannedStmt *pstmt,
857876
break;
858877

859878
case T_CallStmt:
860-
ExecuteCallStmt(castNode(CallStmt, parsetree), params, isAtomicContext, dest);
879+
/*
880+
* In Oracle compatibility mode, CALL statements are non-atomic
881+
* by default when executed at the top level or in a non-atomic
882+
* context, allowing COMMIT/ROLLBACK within the called procedure
883+
* and any nested calls. However, if we're already in an atomic
884+
* context (e.g., called from a function), we must respect that.
885+
*/
886+
{
887+
bool callAtomicContext = isAtomicContext;
888+
889+
if (compatible_db == ORA_PARSER &&
890+
(context == PROCESS_UTILITY_TOPLEVEL ||
891+
context == PROCESS_UTILITY_QUERY_NONATOMIC))
892+
callAtomicContext = false;
893+
894+
ExecuteCallStmt(castNode(CallStmt, parsetree), params,
895+
callAtomicContext, dest);
896+
}
861897
break;
862898

863899
case T_ClusterStmt:

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ CONTEXT: PL/iSQL function transaction_test1(pg_catalog.int4,text) line 6 at COM
5555
COMMIT;
5656
START TRANSACTION;
5757
DO LANGUAGE plisql $$ BEGIN COMMIT; END $$;
58-
ERROR: invalid transaction termination
59-
CONTEXT: PL/iSQL function inline_code_block line 1 at COMMIT
6058
COMMIT;
6159
TRUNCATE test1;
6260
-- not allowed in a function
@@ -482,8 +480,7 @@ begin
482480
raise notice 'length(x) = %', length(x);
483481
end $$;
484482
/
485-
ERROR: invalid transaction termination
486-
CONTEXT: PL/iSQL function inline_code_block line 6 at COMMIT
483+
NOTICE: length(x) = 10000
487484
-- operations on composite types vs. internal transactions
488485
DO LANGUAGE plisql $$
489486
declare

src/pl/plisql/src/pl_gram.y

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

2720+
/* Remember we may need a procedure resource owner */
2721+
plisql_curr_compile->requires_procedure_resowner = true;
2722+
27202723
$$ = (PLiSQL_stmt *)new;
27212724
}
27222725
else
@@ -2744,6 +2747,9 @@ stmt_execsql : K_IMPORT
27442747
new->expr = build_call_expr(T_CWORD, @1, &yylval, &yylloc, yyscanner);
27452748
new->is_call = true;
27462749

2750+
/* Remember we may need a procedure resource owner */
2751+
plisql_curr_compile->requires_procedure_resowner = true;
2752+
27472753
$$ = (PLiSQL_stmt *)new;
27482754
}
27492755
else

0 commit comments

Comments
 (0)