PRAGMA AUTONOMOUS_TRANSACTION Implementation#986
Conversation
WalkthroughAdds PL/iSQL autonomous-transaction support: new pl_autonomous module + header, PRAGMA AUTONOMOUS_TRANSACTION grammar, execution delegation (via dblink/dblink_exec) for autonomous calls, build/install/test updates, and a runtime flag/GUC to prevent recursive autonomous execution. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant PLiSQL_Executor as "PL/iSQL Executor"
participant pl_autonomous as "pl_autonomous"
participant SPI
participant dblink
participant RemoteDB as "Remote DB"
Client->>PLiSQL_Executor: invoke function/procedure
PLiSQL_Executor->>PLiSQL_Executor: check fn_is_autonomous & plisql_inside_autonomous_transaction
alt autonomous and not inside autonomous context
PLiSQL_Executor->>pl_autonomous: plisql_exec_autonomous_function(...)
pl_autonomous->>pl_autonomous: resolve proc name, build connstr & SQL
pl_autonomous->>SPI: use SPI for type conversion/prep (if needed)
pl_autonomous->>dblink: call dblink(connstr, SQL) or dblink_exec(connstr, SQL)
dblink->>RemoteDB: open connection & execute SQL
RemoteDB-->>dblink: return result/status
dblink-->>pl_autonomous: return tuples/status
pl_autonomous->>pl_autonomous: extract/convert return value
pl_autonomous-->>PLiSQL_Executor: return Datum / NULL
end
PLiSQL_Executor->>PLiSQL_Executor: func_end instrumentation & cleanup
PLiSQL_Executor-->>Client: return result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hi, this autonomous transaction looks complicated. I must admit I don't really understand all the details, especially on the pros & cons of design decision details. So no pressure to merge the PR, just wanted to know if this is actually a workable design. The CodeRabbit agent that your team uses is really nice. I actually tried to let Claude work with CodeRabbit to work out some details in my fork: rophy#7 and rophy#9. I hope the results are OK. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pl/plisql/src/pl_gram.y (1)
3224-3323: Keepunreserved_keywordproduction in sync with new “unreserved” tokens
autonomous_transactionandpragmawere added topl_unreserved_kwlist.has unreserved keywords, butunreserved_keywordhere does not includeK_AUTONOMOUS_TRANSACTIONorK_PRAGMA.That has two concrete effects:
- The scanner will now return
K_AUTONOMOUS_TRANSACTION/K_PRAGMAinstead ofT_WORDfor those lexemes, but grammar productions that rely onunreserved_keyword(e.g.decl_varname,ora_function_name,any_identifier,decl_aliasitem) will not accept them, so they can no longer be used as identifiers in those positions.- It contradicts the comment in
pl_unreserved_kwlist.hasking to keep this production consistent with the unreserved kw list.If the intent is for these to behave like other unreserved words (keyword in some contexts, identifier in others), they should be added here (and to
unit_name_keywordif relevant), preserving the existing ordering. For example:unreserved_keyword : K_ABSOLUTE | K_ACCESSIBLE | K_ALIAS | K_AND | K_ARRAY | K_AS | K_ASSERT | K_AUTHID + | K_AUTONOMOUS_TRANSACTION | K_BACKWARD @@ | K_PIPELINED - | K_PG_ROUTINE_OID - | K_PRINT_STRICT_PARAMS + | K_PG_ROUTINE_OID + | K_PRAGMA + | K_PRINT_STRICT_PARAMSIf instead the goal is to treat them as fully reserved (never valid as identifiers), they should probably live in the reserved kw list rather than the unreserved one, and remain absent from this production. Either way, making the choice explicit here avoids surprising parsing differences and keeps the grammar consistent with the kwlist.
🧹 Nitpick comments (3)
src/pl/plisql/src/pl_exec.c (1)
684-710: Autonomous delegation path is sound; consider minor robustness/maintainability tweaksThe autonomous path is wired correctly overall: it’s guarded by
fn_is_autonomousandplisql_inside_autonomous_transaction, avoids firing during validation via thefcinfo->flinfo->fn_oid == func->fn_oidcheck, callsplisql_exec_autonomous_functiononce, then mirrors the normal epilogue (func_end,plisql_destroy_econtext,exec_eval_cleanup,error_context_stackpop) before returning theDatum. That should prevent recursion, preserve error context, and avoid leaks.Two minor follow‑ups you might consider:
- Guard rationale / validation paths: The
fcinfo != NULL && fcinfo->flinfo != NULL && fcinfo->flinfo->fn_oid == func->fn_oidcondition is a subtle contract with call sites to distinguish “real” calls from validation/compilation. It would be good to double‑check all current callers ofplisql_exec_functionobey that invariant and, if so, maybe add a brief comment pointing to the specific validator path this is protecting against (or even anAssert(fcinfo == NULL || fcinfo->flinfo != NULL)above).- Avoid duplicated epilogue logic: The autonomous branch duplicates the normal function epilogue’s
func_end+ cleanup sequence. If more logic ever gets added to the common exit path, this branch could drift. A tiny helper that encapsulates the common “function end + cleanup + error_context_stack pop” would keep the two paths in lockstep.These are optional refinements; the current implementation is functionally correct.
src/pl/plisql/src/pl_autonomous.c (2)
130-143: Potential use-after-free:nspnamefreed after use inpsprintf.The
nspnameis passed toquote_identifier()withinpsprintf, and thenpfree(nspname)is called. However,get_namespace_name()returns a palloc'd string, but the fallbackpstrdup("pg_catalog")also allocates. The issue is thatnspnameis freed unconditionally, but the conditionif (nspname)is always true at that point (either fromget_namespace_namereturning non-NULL or frompstrdup).The logic is actually correct, but the
if (nspname)check is misleading since after the fallback assignment,nspnameis never NULL at line 141. Consider removing the redundant check for clarity:ReleaseSysCache(proctup); - if (nspname) - pfree(nspname); + pfree(nspname); return result;
486-495: Consider quotinghostin connection string for robustness.The
host=localhostis hardcoded and safe, but theportis appended directly without escaping. Whileportcomes from the PostgreSQL GUC and should always be a numeric string, defensive escaping would be more robust:/* Add port if configured */ if (port_str) - appendStringInfo(&connstr_buf, " port=%s", port_str); + { + appendStringInfoString(&connstr_buf, " port='"); + for (const char *p = port_str; *p; p++) + { + if (*p == '\'' || *p == '\\') + appendStringInfoChar(&connstr_buf, '\\'); + appendStringInfoChar(&connstr_buf, *p); + } + appendStringInfoChar(&connstr_buf, '\''); + }However, since
portis a validated GUC that only accepts integer values, the current implementation is safe in practice.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/pl/plisql/src/expected/plisql_autonomous.outis excluded by!**/*.out
📒 Files selected for processing (9)
src/pl/plisql/src/Makefile(4 hunks)src/pl/plisql/src/pl_autonomous.c(1 hunks)src/pl/plisql/src/pl_autonomous.h(1 hunks)src/pl/plisql/src/pl_exec.c(4 hunks)src/pl/plisql/src/pl_gram.y(3 hunks)src/pl/plisql/src/pl_handler.c(6 hunks)src/pl/plisql/src/pl_unreserved_kwlist.h(2 hunks)src/pl/plisql/src/plisql.h(2 hunks)src/pl/plisql/src/sql/plisql_autonomous.sql(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T10:43:25.257Z
Learnt from: syasirs
Repo: IvorySQL/IvorySQL PR: 858
File: src/Makefile.global.in:513-514
Timestamp: 2025-09-02T10:43:25.257Z
Learning: In IvorySQL Makefile.global.in, $(wildcard t/oracle/*.pl) is used instead of t/oracle/*.pl in Oracle TAP test discovery because the t/oracle directory is optional and may not exist in most builds. The wildcard function safely returns empty string when the directory is missing, preventing shell expansion errors.
Applied to files:
src/pl/plisql/src/Makefile
🧬 Code graph analysis (3)
src/pl/plisql/src/pl_autonomous.h (1)
src/pl/plisql/src/pl_autonomous.c (4)
plisql_autonomous_init(61-66)plisql_mark_autonomous_transaction(157-179)plisql_exec_autonomous_function(423-555)plisql_check_dblink_available(186-190)
src/pl/plisql/src/pl_exec.c (1)
src/pl/plisql/src/pl_autonomous.c (1)
plisql_exec_autonomous_function(423-555)
src/pl/plisql/src/pl_handler.c (2)
src/backend/utils/misc/guc.c (1)
DefineCustomBoolVariable(5137-5161)src/pl/plisql/src/pl_autonomous.c (1)
plisql_autonomous_init(61-66)
🔇 Additional comments (18)
src/pl/plisql/src/pl_unreserved_kwlist.h (1)
40-40: New unreserved keywords look correctly wired here
autonomous_transactionandpragmaare added in ASCII order and use distinct token codes (K_AUTONOMOUS_TRANSACTION,K_PRAGMA), which is consistent with the surrounding list. Any follow‑up alignment between this list andunreserved_keywordinpl_gram.yis handled in that file’s review.Also applies to: 105-105
src/pl/plisql/src/plisql.h (1)
1065-1076: Autonomous-transaction flags are cleanly integrated into function and global stateAdding
fn_is_autonomoustoPLiSQL_functionalongside the other per-function flags, and exposingplisql_inside_autonomous_transactionas a global, is a straightforward way to surface autonomous-transaction state to both the compiler and executor paths. Struct layout remains coherent, and the new fields are clearly documented by their naming and comment.Assuming the corresponding definitions, GUC wiring, and initialization are implemented in the C modules, this header change looks good.
Also applies to: 1278-1279
src/pl/plisql/src/pl_exec.c (3)
45-45: pl_autonomous.h include placement looks correctIncluding
pl_autonomous.halongside other PL/iSQL headers is appropriate and keeps the dependency localized to the executor. No issues here.
490-513: Function-level comment matches current plisql_exec_function behaviorThe expanded comment accurately describes the responsibilities and parameters of
plisql_exec_function, including autonomous-transaction support and the role ofprocedure_resowner/atomic. This improves readability without affecting behavior.
9884-9931: No functional change in plisql_anonymous_return_out_parameterOnly the closing brace line is touched here; the implementation of
plisql_anonymous_return_out_parameteritself is unchanged and remains consistent with how anonymous blocks with OUT parameters are handled elsewhere.src/pl/plisql/src/pl_handler.c (3)
62-63: LGTM - Global flag for autonomous transaction detection.The global boolean
plisql_inside_autonomous_transactionis correctly declared and will be controlled by the GUC defined later in_PG_init. This enables detection of recursive autonomous transaction attempts.
202-215: LGTM - Well-designed hidden GUC for recursion prevention.The GUC design is sound:
PGC_USERSETis required since the dblink session must be able toSETthis flag- Hidden flags (
GUC_NOT_IN_SAMPLE | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL) appropriately prevent user discovery while allowing the autonomous session to modify it- The comment clearly documents the design rationale
248-250: LGTM - Initialization hook for autonomous transaction support.The call to
plisql_autonomous_init()correctly registers the syscache invalidation callback for dblink OID caching, placed appropriately near the end of_PG_initafter other module initialization.src/pl/plisql/src/pl_autonomous.h (1)
1-45: LGTM - Clean public header for autonomous transaction support.The header is well-structured with:
- Proper include guard
- Minimal dependency on
plisql.hfor required types- Clear documentation comments for each API function
- Declarations correctly match the implementations in
pl_autonomous.csrc/pl/plisql/src/Makefile (2)
55-57: LGTM - Correct EXTRA_INSTALL for dblink dependency.
EXTRA_INSTALL = contrib/dblinkensures the dblink extension is built and installed in the test instance before running the autonomous transaction tests.
109-109: LGTM - Build dependencies correctly updated.The dependency line properly includes
pl_autonomous.oin the list and addspl_autonomous.has a prerequisite, ensuring correct rebuild ordering when the autonomous transaction module changes.src/pl/plisql/src/pl_autonomous.c (4)
251-275: Consider handling BYTEA and other binary types explicitly.The switch statement handles common scalar types but falls through to
quote_literal_cstrfor everything else. For BYTEA (binary data),OidOutputFunctionCallreturns a hex-encoded string, whichquote_literal_cstrwill quote correctly. However, depending on thebytea_outputsetting, this could produce\x...or escape format, both of which should work but may warrant a note.The current fallback to
quote_literal_cstris safe and handles SQL injection correctly. This is acceptable for initial implementation.
395-404: Double-free ofqueryon error path.In the
PG_CATCHblock,pfree(query)is called at line 399, thenPG_RE_THROW()is called. However, if an error occurs, execution never reaches line 404. But wait -PG_RE_THROW()doesn't return, so line 404 is only reached on success. Let me re-analyze...Actually, on closer inspection:
PG_RE_THROW()does not return, so line 404 is only reached on the success path. The cleanup is correct. However, for clarity and consistency with other cleanup patterns in this file, consider restructuring:The error handling is correct -
PG_RE_THROW()never returns, so line 404 is only executed on success.
1-33: LGTM - File structure and includes are appropriate.The includes cover all necessary headers for the functionality:
- Catalog access for procedure/type lookups
- SPI for query execution
- libpq-be for MyProcPort access
- Syscache invalidation infrastructure
423-426: I'm unable to access the IvorySQL repository directly due to cloning issues, and web search yields no specific documentation about the internal GUCplisql_inside_autonomous_transactionor the recursion prevention mechanism described in your review comment.Manual verification required.
The review comment makes specific claims about:
- The GUC being set in SQL at lines 286 and 296
- Missing recursion checks at the function entry (lines 423-426)
- A potential workaround via
pl_exec.cSince I cannot access the source code to verify these details, and there is no public documentation available for this internal mechanism, you will need to manually verify:
- Whether
plisql_inside_autonomous_transactionis actually checked beforeplisql_exec_autonomous_functionexecutes- Whether recursion guards exist upstream in the calling code (likely in
pl_exec.c)- Whether the dblink-based approach with the GUC setting actually provides adequate recursion prevention
If such checks are confirmed to exist elsewhere in the codebase, the review comment should be updated to reference their location or be resolved. If no checks exist, the concern is valid and warrants correction.
src/pl/plisql/src/sql/plisql_autonomous.sql (3)
301-317: Test 15 relies on psql error behavior - verify expected output file handles error.Test 15 intentionally triggers an error by inserting into
nonexistent_table. The test has commented-out\set ON_ERROR_STOPdirectives. Ensure the expected output file (plisql_autonomous.out) correctly captures this error, or the test may cause the entire regression suite to fail depending on psql settings.
1-454: LGTM - Comprehensive test coverage for autonomous transactions.The test suite provides good coverage including:
- Basic procedure/function execution
- Transaction isolation (autonomous commits survive outer rollbacks)
- Multiple parameter types and NULL handling
- OID invalidation after extension recreation
- Pass-by-reference return types (TEXT, NUMERIC)
- Error handling paths
- Appropriate cleanup at the end
The commented tests for explicit COMMIT/ROLLBACK clearly document the known limitation (Issue #985).
343-367: I'll help you verify the nested autonomous function behavior. Let me search the codebase for the recursion prevention logic and how it handles nested autonomous calls.
<function_calls>
#!/bin/bashSearch for the recursion prevention logic and nested autonomous handling
rg -n "plisql_inside_autonomous" --type c -B 2 -A 5
</function_calls>This will help me understand how the recursion check works. Let me also search for where this variable is defined and used:
<function_calls>
#!/bin/bashFind definition and all usages of the recursion check
rg -n "inside_autonomous_transaction" --type c -B 1 -A 2 | head -100
</function_calls>Let me also look at the actual test file to understand the full context around Test 17:
<function_calls>
#!/bin/bashRead the test file to see the full Test 17 and surrounding context
cat -n src/pl/plisql/src/sql/plisql_autonomous.sql | sed -n '330,380p'
</function_calls>Let me also search for dblink connection handling and how autonomous transactions interact with dblink:
<function_calls>
#!/bin/bashSearch for dblink and autonomous transaction interaction
rg -n "dblink|autonomous" src/pl/plisql/src/ --type c -B 1 -A 3 | head -150
</function_calls>
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
src/pl/plisql/src/pl_autonomous.c (2)
141-142: Unnecessary NULL check.At this point,
nspnameis guaranteed non-NULL (either fromget_namespace_nameor the fallback assignment). The conditional is dead code.ReleaseSysCache(proctup); - if (nspname) - pfree(nspname); + pfree(nspname);
419-425: Unused parameterssimple_eval_estateandsimple_eval_resowner.The function signature includes
EState *simple_eval_estateandResourceOwner simple_eval_resowner, but neither is used in the function body. If these are reserved for future use, consider documenting that. Otherwise, they add unnecessary API surface.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/pl/plisql/src/expected/plisql_autonomous.outis excluded by!**/*.out
📒 Files selected for processing (9)
src/pl/plisql/src/Makefile(4 hunks)src/pl/plisql/src/pl_autonomous.c(1 hunks)src/pl/plisql/src/pl_autonomous.h(1 hunks)src/pl/plisql/src/pl_exec.c(3 hunks)src/pl/plisql/src/pl_gram.y(3 hunks)src/pl/plisql/src/pl_handler.c(6 hunks)src/pl/plisql/src/pl_unreserved_kwlist.h(1 hunks)src/pl/plisql/src/plisql.h(2 hunks)src/pl/plisql/src/sql/plisql_autonomous.sql(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/pl/plisql/src/pl_gram.y
- src/pl/plisql/src/pl_autonomous.h
- src/pl/plisql/src/pl_unreserved_kwlist.h
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T10:43:25.257Z
Learnt from: syasirs
Repo: IvorySQL/IvorySQL PR: 858
File: src/Makefile.global.in:513-514
Timestamp: 2025-09-02T10:43:25.257Z
Learning: In IvorySQL Makefile.global.in, $(wildcard t/oracle/*.pl) is used instead of t/oracle/*.pl in Oracle TAP test discovery because the t/oracle directory is optional and may not exist in most builds. The wildcard function safely returns empty string when the directory is missing, preventing shell expansion errors.
Applied to files:
src/pl/plisql/src/Makefile
🧬 Code graph analysis (3)
src/pl/plisql/src/pl_autonomous.c (8)
src/backend/utils/cache/inval.c (1)
CacheRegisterSyscacheCallback(1811-1842)src/backend/commands/extension.c (1)
get_extension_oid(166-181)src/common/stringinfo.c (3)
initStringInfo(96-100)appendStringInfoString(229-233)appendStringInfo(144-166)src/backend/utils/fmgr/fmgr.c (1)
OidOutputFunctionCall(1819-1826)src/backend/parser/parse_func.c (1)
LookupFuncName(2414-2459)src/backend/executor/spi.c (4)
SPI_connect(96-100)SPI_execute(605-636)SPI_getbinval(1278-1292)SPI_finish(186-220)src/include/utils/palloc.h (1)
MemoryContextSwitchTo(123-130)src/backend/utils/misc/guc.c (1)
GetConfigOption(4359-4400)
src/pl/plisql/src/pl_handler.c (2)
src/backend/utils/misc/guc.c (1)
DefineCustomBoolVariable(5137-5161)src/pl/plisql/src/pl_autonomous.c (1)
plisql_autonomous_init(61-66)
src/pl/plisql/src/pl_exec.c (1)
src/pl/plisql/src/pl_autonomous.c (1)
plisql_exec_autonomous_function(423-555)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: oracle_regression (ubuntu-latest)
- GitHub Check: meson_build (ubuntu-latest)
- GitHub Check: oracle_pg_regression (ubuntu-latest)
- GitHub Check: build (ubuntu-latest)
- GitHub Check: contrib_regression
- GitHub Check: pg_regression (ubuntu-latest)
🔇 Additional comments (32)
src/pl/plisql/src/sql/plisql_autonomous.sql (9)
1-15: Setup is clear and complete.Test table and dblink extension correctly provisioned. The schema (id, msg, tx_state) is well-suited for verifying autonomous transaction semantics (commit/rollback isolation).
20-96: Test 1–4: Basic functionality and parameter handling look solid.Each test follows a consistent pattern: define, commit, call, verify with
SELECT. Tests progressively exercise no parameters → scalar parameters → multiple types (INT, TEXT, BOOLEAN). The isolation test (lines 53–71) is particularly good: it confirms autonomous commits survive outerROLLBACK, which is the core semantic.
100-130: Tests 5–6: NULL handling and sequential calls well covered.Test 5 (lines 100–111) validates that NULL parameters are properly passed and handled with
COALESCE. Test 6 (lines 116–130) confirms multiple back-to-back autonomous calls don't interfere with each other. Both are essential for real-world use.
143-166: Test 8: Persistence semantics verified correctly.The mid-suite
TRUNCATEat line 143 is intentional for test isolation, not a red flag. The test cleanly demonstrates that autonomous inserts persist even when the outer transaction rolls back. The inlineSELECT COUNT(*)at line 162 within the transaction is a nice touch to show visibility.
171-192: Test 9: OID invalidation testing is thorough but operationally risky.Dropping and recreating the dblink extension (lines 185–186) tests the syscache invalidation callback. This is essential for confirming cached OID correctness. However, if this test fails mid-execution, subsequent tests depend on dblink being present. In a production test harness, this test should be isolated or ordered last. For a single-file test, this is acceptable since cleanup happens afterward.
Confirm whether this test file runs as a single atomic unit or if individual tests can be reordered/skipped. If it's meant to be run with
psql -f, consider whether dropping dblink mid-suite could cause issues if an earlier test fails.
197-429: Tests 10–20: Comprehensive type coverage and nested/error cases.Excellent progression through return types (INT, TEXT, NULL, NUMERIC, DATE, BOOLEAN), nested autonomous calls (Test 17, lines 343–367), and pass-by-reference handling. Test 18–20 specifically exercise NUMERIC (variable-length), DATE, and BOOLEAN to stress datumCopy() code paths. Test 15 (error handling) inserts into a nonexistent table to test exception cleanup (SPI_finish, pfree).
240-296: Commented COMMIT/ROLLBACK tests appropriately documented.Four tests (Tests 12–14) exercising explicit COMMIT/ROLLBACK and conditional transaction control are commented with Issue #985 references, making it clear these are known limitations rather than oversights. This is good practice for documenting intent.
437-454: Cleanup is comprehensive and matches all defined procedures/functions.All 17 procedures/functions plus the test table are dropped. The cleanup will succeed even if earlier tests failed (assuming CASCADE is handled gracefully). No dangling objects.
301-318: Verify test execution and error-handling behavior for intentional errors in test_function_error().Lines 315–317 appear to have
\set ON_ERROR_STOP off/ondirectives commented out around an expected error test. Confirm: (1) whether the test harness or runner catches errors automatically, (2) the intended execution mode (manual interactive testing vs. automated suite), and (3) whether execution should halt or continue past this intentional error. Update the code or documentation accordingly.src/pl/plisql/src/plisql.h (2)
1067-1067: LGTM!The
fn_is_autonomousfield is well-placed alongside other function metadata flags likehas_exception_block. This correctly extends the function struct to track autonomous transaction capability at compile time.
1280-1281: LGTM!The extern declaration for
plisql_inside_autonomous_transactionfollows the established pattern for other PL/iSQL global flags (e.g.,plisql_check_asserts,plisql_print_strict_params). The blank line after the declaration maintains consistent formatting.src/pl/plisql/src/pl_handler.c (5)
27-27: LGTM!Header include is correctly placed with other module-specific headers.
62-63: LGTM!Clear initialization of the recursion-prevention flag with a descriptive comment.
154-165: LGTM!Good documentation update describing the initialization flow, including the new autonomous-transaction support. The warning about not making the function static is helpful for maintainability.
202-215: Verify security implications ofPGC_USERSETfor internal flag.The comment correctly explains why
PGC_USERSETis needed (dblink sessions must SET it). However, this means any user can manually setplisql.inside_autonomous_transaction = trueto bypass autonomous transaction execution (causing an error), or set it tofalseto potentially bypass the recursion guard.The hiding flags (
GUC_NOT_IN_SAMPLE | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL) provide obscurity but not security. Consider documenting this trade-off or adding a check in the autonomous execution path that the flag is only being set from a trusted context (though this may be impractical with dblink).
248-250: LGTM!Initialization call is correctly placed after other module setup and before marking
inited = true. The comment accurately describes the purpose.src/pl/plisql/src/Makefile (6)
42-42: LGTM!New object file correctly added to the build in alphabetical order.
56-58: LGTM!Good addition of
EXTRA_INSTALL = contrib/dblinkwith a clear comment explaining the dependency. This ensures the dblink extension is built and installed for the regression tests.
66-66: LGTM!Test file added to the regression suite.
95-95: LGTM!Header installation follows the existing pattern for other public headers (
plisql.h,pl_subproc_function.h,pl_package.h).
104-104: LGTM!Uninstall rule correctly mirrors the install rule.
110-110: LGTM!Dependency rule correctly updated to include both
pl_autonomous.oandpl_autonomous.h, ensuring proper rebuild when the autonomous transaction module changes.src/pl/plisql/src/pl_exec.c (3)
46-46: Include ofpl_autonomous.his appropriate and scoped correctlyThe new include cleanly introduces the autonomous-transaction API (
plisql_exec_autonomous_function,plisql_inside_autonomous_transaction) intopl_exec.cwithout impacting existing dependencies. No issues here.
487-515: Updatedplisql_exec_functiondocumentation and prototype look consistentThe expanded comment accurately reflects the current behavior and signature (simple-eval estate, both resource owners, and
atomicflag), including autonomous transactions and set-returning results. The added forward declaration forplisql_anonymous_return_out_parametermatches its definition below and is correctly typed.
517-538: Verify all call sites ofplisql_exec_functionpopulateprocedure_resownerandatomiccorrectlyThe concern about caller consistency is valid. Ensure that every invocation of
plisql_exec_functionpasses appropriate values:
- Expression/SELECT paths:
procedure_resowner = NULL,atomic = true- CALL/DO paths: appropriate long-lived
procedure_resowner,atomic = falseInconsistent parameter passing across call sites could lead to subtle lifecycle or atomicity bugs.
src/pl/plisql/src/pl_autonomous.c (7)
34-66: LGTM!The syscache invalidation callback pattern for caching dblink function OIDs is correctly implemented. The callback properly resets both cached OIDs when pg_proc changes, ensuring stale OIDs are never used.
78-103: LGTM!Defensive checks for
MyProcPortanddatabase_nameare appropriate. The function correctly handles edge cases like background workers and standalone mode with clear error messages.
157-179: LGTM!The validation logic is correct, and deferring the dblink availability check to execution time (rather than procedure creation time) is a sensible design choice that avoids dependency issues during DDL.
186-190: LGTM!Clean implementation using
get_extension_oidwithmissing_ok=true.
280-300: LGTM on SQL construction with proper quoting.The use of
quote_literal_cstrfor non-numeric types and direct formatting for validated numeric types provides adequate SQL injection protection. The session variable settings (ivorysql.compatible_mode,plisql.inside_autonomous_transaction) are correctly embedded.
386-391: Good memory context handling for pass-by-reference return values.Correctly switches to
fn_mcxtbefore copying the result to ensure it survives afterSPI_finish()releases SPI memory.
503-515: Consistent error handling with cleanup across both function and procedure paths.Both paths correctly use
PG_TRY/PG_CATCHto ensure memory cleanup (connstr_buf.data,sql,dbname) before re-throwing. Good defensive programming.Also applies to: 530-544
| /* Add host if configured */ | ||
| host_str = GetConfigOption("listen_addresses", false, false); | ||
| if (host_str && strcmp(host_str, "*") != 0 && strcmp(host_str, "") != 0) | ||
| { | ||
| /* Use localhost for local connections */ | ||
| appendStringInfoString(&connstr_buf, " host=localhost"); | ||
| } | ||
|
|
||
| /* Add port if configured */ | ||
| if (port_str) | ||
| appendStringInfo(&connstr_buf, " port=%s", port_str); |
There was a problem hiding this comment.
Clarify the listen_addresses check logic—the current analysis contains an error.
The condition if (host_str && strcmp(host_str, "*") != 0 && strcmp(host_str, "") != 0) actually adds host=localhost when listen_addresses is 0.0.0.0, not skips it. However, there is a legitimate concern: if listen_addresses is set to a specific interface (e.g., 192.168.1.1), then localhost (which resolves to 127.0.0.1) may not be reachable over TCP, requiring a Unix socket connection instead.
The current strategy—adding host=localhost only when listen_addresses is explicitly configured—is reasonable for local connections, since Unix sockets are used as a fallback. However, consider documenting this assumption or validating that the heuristic works for your deployment scenarios.
Port validation is unnecessary; PostgreSQL's port GUC is already validated as an integer in the range 1–65535.
Hi rophy, Thanks for your effort and output. It will take several days to thoroughly study the design and implementation specifics. Please appreciate your patience.
Sounds interesting. |
@coderabbitai See here, let's have a poem from you |
|
Tip For best results, initiate chat on the files or code changes. @OreoYang, here's a poem for you! 🎭 Ode to Autonomous Transactions Through layers of code, connections unfold, From parser's grasp to handler's care, Through rophy's work and thoughtful review, So here's to code that dares to be, May your transactions always commit successfully! 😊 |
Add Oracle-compatible autonomous transactions using dblink to execute functions/procedures in separate database sessions with independent transaction control.
- Raise error on concurrent schema drop instead of pg_catalog fallback - Add spi_connected flag to guard SPI_finish() in catch block - Add argument count bounds check before accessing proargtypes - Update expected test output to match actual format
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/pl/plisql/src/pl_gram.y (1)
35-35: Grammar hook forPRAGMA AUTONOMOUS_TRANSACTIONlooks correctIncluding
pl_autonomous.h, addingK_AUTONOMOUS_TRANSACTION, and routingPRAGMA AUTONOMOUS_TRANSACTION;throughplisql_mark_autonomous_transaction(plisql_curr_compile, @1, yyscanner)cleanly enforces that the pragma appears in the declarative section and avoids implicit declarations.One behavioral detail:
K_AUTONOMOUS_TRANSACTIONis not part ofunreserved_keyword, soautonomous_transactioncannot be used as an identifier (unlike many other pragma-related tokens such asK_EXCEPTION_INIT). If you want it to behave as an unreserved keyword (closer to how other pragma keywords are treated), consider adding it tounreserved_keyword(andunit_name_keywordif appropriate); otherwise this is fine as a deliberate choice.Also applies to: 315-315, 842-846
src/pl/plisql/src/pl_exec.c (1)
685-711: Autonomous delegation branch: verify call-site assumptions and consider centralizing cleanupThe delegation logic looks sound overall (good use of
fn_is_autonomous,plisql_inside_autonomous_transaction, OID match, and symmetricfunc_end+ cleanup), but a few points are worth double‑checking and possibly tightening:
Call-site / OID matching assumption
The guard:
fcinfo != NULL && fcinfo->flinfo != NULL && fcinfo->flinfo->fn_oid == func->fn_oidassumes that for all execution contexts where
fn_is_autonomousshould trigger (top-level functions, procedures, package-body routines, nested subprocedures),fcinfo->flinfo->fn_oidis the OID offunc->fn_oid. If any path (e.g., some nested subprocedure or package call) uses a differentFmgrInfo/OID plumbing, autonomous routines in that context will silently execute non-autonomously.Please verify that all intended autonomous entry points reach
plisql_exec_functionwith this equality satisfied, and that internal validation/compilation paths either passfcinfo == NULLor have afn_oidmismatch so they correctly skip delegation.Autonomous recursion guard lifecycle
The recursion prevention here relies entirely on
!plisql_inside_autonomous_transaction. That means the dblink-launched session must set this flag (via the GUC) before its first call intoplisql_exec_functionfor the autonomous routine, or you’ll recursively recurse back intoplisql_exec_autonomous_function. Please ensureplisql_autonomous_init()(or equivalent) is invoked early enough in the autonomous backend lifecycle.Shared cleanup duplication
The autonomous branch manually duplicates the normal-function exit cleanup:
if (*plisql_plugin_ptr && (*plisql_plugin_ptr)->func_end) ((*plisql_plugin_ptr)->func_end) (&estate, func); plisql_destroy_econtext(&estate); exec_eval_cleanup(&estate); error_context_stack = plerrcontext.previous;The same sequence (plus additional logic) exists in the non-autonomous path at the end of
plisql_exec_function. To avoid drift if more steps are added later (e.g., extra hooks or state), consider factoring this into a small helper (e.g.,plisql_function_finish(&estate, func, plerrcontext)) and reusing it from both branches.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/pl/plisql/src/expected/plisql_autonomous.outis excluded by!**/*.out
📒 Files selected for processing (9)
src/pl/plisql/src/Makefile(4 hunks)src/pl/plisql/src/pl_autonomous.c(1 hunks)src/pl/plisql/src/pl_autonomous.h(1 hunks)src/pl/plisql/src/pl_exec.c(3 hunks)src/pl/plisql/src/pl_gram.y(3 hunks)src/pl/plisql/src/pl_handler.c(6 hunks)src/pl/plisql/src/pl_unreserved_kwlist.h(1 hunks)src/pl/plisql/src/plisql.h(2 hunks)src/pl/plisql/src/sql/plisql_autonomous.sql(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/pl/plisql/src/pl_handler.c
- src/pl/plisql/src/pl_autonomous.h
- src/pl/plisql/src/pl_unreserved_kwlist.h
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T10:43:25.257Z
Learnt from: syasirs
Repo: IvorySQL/IvorySQL PR: 858
File: src/Makefile.global.in:513-514
Timestamp: 2025-09-02T10:43:25.257Z
Learning: In IvorySQL Makefile.global.in, $(wildcard t/oracle/*.pl) is used instead of t/oracle/*.pl in Oracle TAP test discovery because the t/oracle directory is optional and may not exist in most builds. The wildcard function safely returns empty string when the directory is missing, preventing shell expansion errors.
Applied to files:
src/pl/plisql/src/Makefile
🧬 Code graph analysis (2)
src/pl/plisql/src/pl_autonomous.c (8)
src/backend/utils/cache/inval.c (1)
CacheRegisterSyscacheCallback(1811-1842)src/backend/utils/error/elog.c (4)
errcode(853-864)errmsg(1070-1086)errdetail(1203-1218)errhint(1317-1332)src/backend/utils/cache/lsyscache.c (1)
get_namespace_name(3848-3865)src/pl/plisql/src/pl_scanner.c (1)
plisql_scanner_errposition(613-627)src/common/stringinfo.c (4)
initStringInfo(96-100)appendStringInfoString(229-233)appendStringInfo(144-166)appendStringInfoChar(241-252)src/backend/parser/parse_func.c (1)
LookupFuncName(2414-2459)src/backend/executor/spi.c (4)
SPI_connect(96-100)SPI_execute(605-636)SPI_getbinval(1278-1292)SPI_finish(186-220)src/backend/utils/misc/guc.c (1)
GetConfigOption(4359-4400)
src/pl/plisql/src/pl_exec.c (1)
src/pl/plisql/src/pl_autonomous.c (1)
plisql_exec_autonomous_function(435-567)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: contrib_regression
- GitHub Check: pg_regression (ubuntu-latest)
- GitHub Check: build (ubuntu-latest)
- GitHub Check: oracle_regression (ubuntu-latest)
- GitHub Check: meson_build (ubuntu-latest)
- GitHub Check: oracle_pg_regression (ubuntu-latest)
🔇 Additional comments (16)
src/pl/plisql/src/plisql.h (1)
1067-1068: Autonomous flags are well-integrated into core PL/iSQL structuresAdding
fn_is_autonomoustoPLiSQL_functionalongside other per-function flags, and exposingplisql_inside_autonomous_transactionfor the GUC-backed execution-context flag, is consistent with the existing design and should default correctly with zeroed allocations. Note that plugins that depend on the exactPLiSQL_functionlayout will need a rebuild against this updated header, which is expected when introducing a feature of this scope.If you ship out-of-tree instrumentation plugins, please recompile them against this new header to avoid layout mismatches.
Also applies to: 1280-1281
src/pl/plisql/src/Makefile (1)
42-42: Build/test wiring for autonomous support is consistent; mind the new dblink dependency
- Adding
pl_autonomous.otoOBJSand to the explicit dependency line, and exportingpl_autonomous.hvia install/uninstall, correctly integrates the new module into the core PL/iSQL shared library and its public headers.- Extending
REGRESSwithplisql_autonomousensures the autonomous-transaction test suite runs underoracle-(install)check.EXTRA_INSTALL = contrib/dblinkmakes dblink a required installed extension for this PL’s tests (and possibly for installs, depending on your top-level rules), which matches the implementation choice but tightens the build-time dependency on contrib. This is fine if dblink is always built in your supported configurations; otherwise, consider documenting this requirement or guarding it with the same conditions under which contrib/dblink is available.Please verify in your CI/build matrix that environments which skip building contrib still either (a) build/install
contrib/dblinkor (b) are adjusted to skip autonomous PL/iSQL tests accordingly.Also applies to: 56-59, 66-67, 95-96, 104-105, 110-111
src/pl/plisql/src/pl_exec.c (1)
46-46: Autonomous header inclusion is appropriateIncluding
pl_autonomous.hhere is the right integration point for the new autonomous-transaction delegation path; no issues spotted.src/pl/plisql/src/sql/plisql_autonomous.sql (5)
7-15: LGTM: Clean test setup.The extension installation and table creation are appropriate for the test suite. The
tx_statecolumn with a default value helps document the expected state of each test row.
17-131: LGTM: Comprehensive basic test coverage.Tests 1-6 thoroughly verify core autonomous transaction functionality including parameter handling, transaction isolation, multiple data types, NULL handling, and sequential calls. The isolation test (Test 3) correctly demonstrates that autonomous commits survive outer rollbacks.
236-296: Known limitation properly documented.The commented tests for explicit COMMIT/ROLLBACK within autonomous blocks correctly document the known limitation referenced in Issue #985. The comments clearly explain the expected failures and the current behavior, which aligns with the PR summary.
314-317: Verify error test execution behavior.The
\set ON_ERROR_STOP off/ondirectives are commented out, meaning Test 15 will cause the test script to fail and stop execution at the intentional error. If this test is meant to verify graceful error handling without stopping the test suite, uncomment these directives.Do you want the error handling test to continue execution after the error, or should it stop the test suite? If it should continue, uncomment lines 315 and 317.
437-454: LGTM: Complete cleanup.All created test objects (8 procedures, 9 functions, and 1 table) are properly dropped in the cleanup section.
src/pl/plisql/src/pl_autonomous.c (8)
34-66: LGTM: Correct OID caching with invalidation.The OID caching strategy with syscache invalidation callback is correctly implemented. Both
dblink_exec_oidanddblink_oidare properly reset when pg_proc changes, ensuring stale function OIDs are not used after extension drop/recreate.
78-103: LGTM: Robust database name retrieval.The function correctly validates that both
MyProcPortanddatabase_nameare available before use, with clear error messages explaining the context (background processes vs. missing connection info). The use ofpstrdupensures the returned string is allocated in the caller's memory context.
113-148: LGTM: Secure name construction with proper error handling.The function correctly constructs a schema-qualified, SQL-injection-safe function name using
quote_identifierfor both components. The concurrent schema drop scenario is properly handled with a clear error message, as noted in the addressed past review comments.
161-183: LGTM: Proper pragma validation.The function correctly validates placement and prevents duplicate pragmas. Deferring the dblink availability check to execution time (lines 176-180) is a sound design choice that avoids issues during procedure creation.
190-194: LGTM: Clean extension availability check.Uses the standard PostgreSQL API appropriately with
missing_ok=trueto avoid errors when the extension is not installed.
210-316: LGTM: Comprehensive SQL construction with proper quoting.The function correctly:
- Validates argument count (addresses past review comment)
- Handles NULL arguments explicitly
- Applies type-appropriate formatting (unquoted numerics, boolean conversion, quoted literals)
- Uses
quote_literal_cstrfor string safety- Sets required session flags (
ivorysql.compatible_modeandplisql.inside_autonomous_transaction)- Manages memory correctly (returns
sql.datafor caller to free)
327-420: LGTM: Robust execution with proper error handling.The function correctly implements autonomous function execution with:
- OID caching for
dblink()- Proper SPI connection tracking with
spi_connectedflag (addresses past review comment)- Correct result extraction and NULL handling
- Memory context switching for pass-by-reference types to ensure data survives
SPI_finish()- Comprehensive error cleanup in the catch block
435-567: LGTM: Complete autonomous execution orchestration.The function correctly:
- Builds libpq-safe connection strings with proper escaping for single quotes and backslashes
- Branches between function (SELECT via dblink + SPI) and procedure (CALL via dblink_exec) paths
- Includes comprehensive error handling with cleanup in both paths
- Returns appropriate values (actual Datum for functions, NULL with
isnull=truefor procedures)The
listen_addresseslogic (lines 497-503) was discussed in past review comments and is reasonable for local connections with Unix socket fallback.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/pl/plisql/src/pl_exec.c (1)
491-515:fcinfocontract is now documented as non-NULL but still not enforced in codeThe updated comment correctly reflects the implementation’s assumption that
fcinfo“must be non-NULL for executable calls,” butplisql_exec_functionstill unconditionally dereferencesfcinfo(e.g., argument loading andfcinfo->resultinfo/fcinfo->isnull) with no defensive check.Consider adding an early assertion or explicit error to make the contract fail-fast and self-documenting, e.g.:
Assert(fcinfo != NULL); /* or */ if (fcinfo == NULL) elog(ERROR, "plisql_exec_function called with NULL fcinfo");This also guards against any future internal caller accidentally passing
NULL.
🧹 Nitpick comments (1)
src/pl/plisql/src/sql/plisql_autonomous.sql (1)
298-317: Error-handling test intentionally expects failure. Test 15 (lines 301–317) inserts into a nonexistent table to triggerPG_CATCHcleanup paths (pfree, SPI_finish). The commented-out\set ON_ERROR_STOP off/on(lines 315, 317) is noted but doesn't impede test execution—the error is expected and the test validates graceful failure. For clarity in CI/automation, consider uncommenting these directives so error handling doesn't halt the full suite unexpectedly.- -- \set ON_ERROR_STOP off - SELECT test_function_error(); - -- \set ON_ERROR_STOP on + \set ON_ERROR_STOP off + SELECT test_function_error(); + \set ON_ERROR_STOP on
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/pl/plisql/src/expected/plisql_autonomous.outis excluded by!**/*.out
📒 Files selected for processing (2)
src/pl/plisql/src/pl_exec.c(3 hunks)src/pl/plisql/src/sql/plisql_autonomous.sql(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pl/plisql/src/pl_exec.c (1)
src/pl/plisql/src/pl_autonomous.c (1)
plisql_exec_autonomous_function(435-567)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: meson_build (ubuntu-latest)
- GitHub Check: contrib_regression
- GitHub Check: oracle_pg_regression (ubuntu-latest)
- GitHub Check: pg_regression (ubuntu-latest)
- GitHub Check: build (ubuntu-latest)
- GitHub Check: oracle_regression (ubuntu-latest)
🔇 Additional comments (7)
src/pl/plisql/src/pl_exec.c (2)
46-46: Include ofpl_autonomous.hcorrectly wires in autonomous-transaction supportThe new include looks appropriate and localized; no issues from this file’s perspective.
685-711: Autonomous delegation path may bypass local SRF/OUT handling; verify full parity with normal executionThe new autonomous branch delegates cleanly to
plisql_exec_autonomous_functionand mirrors pluginfunc_endand econtext cleanup. However, verify the following behavioral guarantees:
Set-returning functions:
This earlyreturn result;bypasses the laterestate.retisset/ReturnSetInfohandling inplisql_exec_function. Confirm thatplisql_exec_autonomous_function:
- Fully handles
fcinfo->resultinfowhenfunc->fn_retsetis true (materializes a tuplestore and fillsReturnSetInfoidentically to the normal path), and- Returns a
Datum/fcinfo->isnullpair in final form for both scalar and SRF use-cases.Add tests for
RETURNS SETOFautonomous functions to ensure callers see identical behavior to the non-autonomous path.Anonymous blocks and OUT parameters:
This path skips the anonymous-block OUT propagation andanonymous_have_outparamlogic. IfPRAGMA AUTONOMOUS_TRANSACTIONis forbidden for anonymous DO blocks, document that restriction; otherwise, implement corresponding OUT-parameter handling in the autonomous path or explicitly reject that combination.Validation / internal calls:
Thefcinfo->flinfo->fn_oid == func->fn_oidguard prevents delegating validation contexts. Verify that:
- All real, user-visible autonomous calls satisfy this predicate, including nested subprocedures and package-body routines.
- All internal plumbing/validator paths never call this with matching OIDs, preventing accidental dblink recursion.
Add a comment in
pl_exec.creferencing where these guarantees are upheld (e.g., inpl_autonomous.cor test suite).src/pl/plisql/src/sql/plisql_autonomous.sql (5)
1-15: Comprehensive autonomous-transaction test suite with clear documentation. Setup is well-structured: dblink installed, test table created with appropriate schema, cleanup deferred to end. Inline comments clearly explain test purpose and expected behavior. Good coverage of parameter types, return types, and error paths.
168-192: Test 9 (OID invalidation) is critical for cache correctness. The test validates that the GUC-backed recursion-prevention mechanism survives extension drop/recreate. TheDROP EXTENSION dblink CASCADE(line 185) is intentional here to force OID invalidation and test the syscache invalidation callback. This is a key verification for the feature's robustness, and the test design is sound.
235-296: Commented tests (12–14) appropriately document Issue #985 limitation. Tests for explicitCOMMIT/ROLLBACKwithin autonomous blocks are correctly flagged as unsupported and deferred to future work. Comments clearly explain why (PL/iSQL lacks transaction-control statements), cite the issue, and provide example code for when the limitation is lifted. This is good documentation for future maintainers.
340-367: Test 17 (nested autonomous calls) validates multi-SPI-context correctness. Bothinner_functionandouter_functiondeclarePRAGMA AUTONOMOUS_TRANSACTION, confirming that nested autonomous execution paths don't corrupt stack or SPI state. The expected return value comment (line 365) correctly traces the calculation. This is an important integration test for the feature.
436-453: Cleanup is complete and correct. All procedures, functions, and the test table are dropped in reverse order of creation. No dangling artifacts left in the test database. Proper tear-down for repeatable test runs.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/pl/plisql/src/sql/plisql_autonomous.sql (1)
1-454: Comprehensive test suite with good coverage; verify CI compatibility for error handling.The test suite covers 20+ scenarios including basic calls, isolation, return types, nested calls, OID invalidation, and error handling. Structure is consistent and intentional design decisions (e.g., Issue #985 references) are well-documented.
Recommendations for robustness:
- Test isolation: Confirm the OID invalidation test (line 185–186) runs isolated from other tests and does not cause unexpected cascading drops.
- Error handling test (lines 301–317): Verify this pattern works in your automated test harness; if not, consider restructuring to use explicit error-catching logic or document as manual-only.
- Consider adding a negative test (e.g., recursive autonomous call without GUC guard, malformed PRAGMA) if the C-level guard is not visible from SQL tests.
src/pl/plisql/src/pl_exec.c (2)
528-535:fcinfocontract +function_frominitialization look soundAsserting
fcinfo != NULLup front is consistent with the new API contract and with the function’s pervasive use offcinfo(e.g., argument loading, resultinfo handling,plisql_function_from(fcinfo)). Computingfunction_fromimmediately after is straightforward and keeps the later logic unchanged.If you ever intend to call
plisql_exec_functionin non-executable/validation contexts with a NULLfcinfo, consider tightening the contract by emitting a clear ERROR instead of just anAssertso production builds fail fast with a message rather than a null dereference, but this is optional given the current design.
690-716: Autonomous delegation path is well‑guarded; consider minor observability tweak and verify return-type parityThe new delegation to
plisql_exec_autonomous_functionis carefully gated:
- Only fires for
func->fn_is_autonomousand when not already inside an autonomous transaction (!plisql_inside_autonomous_transaction).- Skips internal/validation contexts by requiring a real
fcinfo->flinfoand matchingfn_oid.- Leaves non-autonomous and nested/validation paths on the existing top-level-block execution.
Cleanup and hooks mirror the normal path:
func_begruns before the branch,func_endis called in the autonomous branch, the eval econtext is destroyed,exec_eval_cleanupis called, anderror_context_stackis restored before returning.Two small follow-ups to consider:
Instrumentation visibility: before calling
func_end, you might want to populateestate.retval,estate.retisnull, andestate.rettypefromresult/fcinfo->isnullfor scalar-returning functions so instrumentation plugins that inspectestatesee a result consistent with non-autonomous execution. This is optional but would make the plugin view more uniform.Behavioral parity check: because this branch bypasses the local return-casting path (tuple coercion, domain checks, SRF materialization), all of that now relies on
plisql_exec_autonomous_functionand helpers. Please ensure you have tests confirming that autonomous functions and procedures behave identically to non-autonomous ones across:
- scalar, composite, and domain return types,
- set-returning functions (including
ReturnSetInfobehavior),- procedures with IN/OUT/INOUT parameters.
From this file’s perspective the wiring is correct, but those behaviors are enforced in
pl_autonomous.c.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/pl/plisql/src/expected/plisql_autonomous.outis excluded by!**/*.out
📒 Files selected for processing (2)
src/pl/plisql/src/pl_exec.c(4 hunks)src/pl/plisql/src/sql/plisql_autonomous.sql(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pl/plisql/src/pl_exec.c (2)
src/pl/plisql/src/pl_subproc_function.c (1)
plisql_function_from(1121-1135)src/pl/plisql/src/pl_autonomous.c (1)
plisql_exec_autonomous_function(435-567)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: oracle_regression (ubuntu-latest)
- GitHub Check: oracle_pg_regression (ubuntu-latest)
- GitHub Check: contrib_regression
- GitHub Check: build (ubuntu-latest)
- GitHub Check: meson_build (ubuntu-latest)
- GitHub Check: pg_regression (ubuntu-latest)
🔇 Additional comments (6)
src/pl/plisql/src/sql/plisql_autonomous.sql (4)
1-95: Setup and basic tests look sound.Extension creation, table setup, and Tests 1–4 follow expected patterns. PRAGMA placement in the DECLARE section aligns with documented syntax.
171-192: OID invalidation test: verify CASCADE scope.Line 185 uses
DROP EXTENSION dblink CASCADE;to test OID invalidation and revalidation. While the extension is recreated at line 186, CASCADE could drop dependent functions or procedures if the test suite runs in a persistent environment. Ensure this test runs in isolation or document expected side effects.
240-296: Commented-out tests appropriately documented.Tests 12–14 are correctly disabled with clear references to Issue #985 (lack of COMMIT/ROLLBACK support in autonomous blocks). The comments explain the limitation and expected failures well, making it easy to re-enable these tests once the issue is resolved.
437-454: Cleanup is thorough and well-ordered.All test procedures, functions, and the test table are explicitly dropped. The order (procedures before functions, then table) respects dependency constraints.
src/pl/plisql/src/pl_exec.c (2)
46-46: Include ofpl_autonomous.his appropriateThe new header include is placed consistently with other PL/iSQL-specific headers and is the right way to expose
plisql_exec_autonomous_functionhere. No issues.
491-515: Updatedplisql_exec_functionAPI comment now matches implementationThe expanded doc block clearly describes the function’s responsibilities, including autonomous transactions and SRF behavior, and correctly states that
fcinfomust be non-NULL for executable calls, which matches all current uses and the unconditional dereferences in the body.
| CREATE OR REPLACE FUNCTION test_function_error() RETURN INT AS | ||
| DECLARE | ||
| PRAGMA AUTONOMOUS_TRANSACTION; | ||
| BEGIN | ||
| -- This will fail because nonexistent_table doesn't exist | ||
| -- Tests PG_CATCH cleanup (pfree and SPI_finish) | ||
| INSERT INTO nonexistent_table VALUES (999); | ||
| RETURN 1; | ||
| END; | ||
| / | ||
|
|
||
| COMMIT; | ||
|
|
||
| -- This should fail gracefully with proper error message | ||
| -- \set ON_ERROR_STOP off | ||
| SELECT test_function_error(); | ||
| -- \set ON_ERROR_STOP on |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check if the file exists and read the specific lines in question
wc -l src/pl/plisql/src/sql/plisql_autonomous.sqlRepository: IvorySQL/IvorySQL
Length of output: 178
🏁 Script executed:
# Read lines 301-317 to see the actual code
sed -n '301,317p' src/pl/plisql/src/sql/plisql_autonomous.sqlRepository: IvorySQL/IvorySQL
Length of output: 178
🏁 Script executed:
# Get broader context around these lines to understand the test structure
sed -n '295,325p' src/pl/plisql/src/sql/plisql_autonomous.sqlRepository: IvorySQL/IvorySQL
Length of output: 178
🏁 Script executed:
# Search for other tests in the file to understand the test pattern
grep -n "CREATE OR REPLACE FUNCTION test_" src/pl/plisql/src/sql/plisql_autonomous.sql | head -20Repository: IvorySQL/IvorySQL
Length of output: 178
🏁 Script executed:
# Look for test harness or execution setup files
find . -type f \( -name "*.sh" -o -name "*.py" -o -name "Makefile" -o -name "*.mk" \) | grep -E "(test|harness|run)" | head -20Repository: IvorySQL/IvorySQL
Length of output: 178
🏁 Script executed:
# Search for \set commands in the sql directory to see if this pattern is used elsewhere
rg "\\\\set" src/pl/plisql/src/sql/ -A 2 -B 2Repository: IvorySQL/IvorySQL
Length of output: 178
🌐 Web query:
IvorySQL test harness plisql testing automated CI error handling
💡 Result:
Short guide — testing PL/SQL/PL/pgSQL on IvorySQL with an automated CI test harness and robust error handling.
Key tools
- pgTAP for unit tests of PL/pgSQL / PL/SQL routines (assertions, throws_ok/lives_ok, runtests()). [1]
- PostgreSQL regression harness (pg_regress / make installcheck) for integration/regression tests shipped with the server. Works for IvorySQL (IvorySQL is a PostgreSQL fork so the same test flow applies). [2][3]
- Standard CI runners (GitHub Actions / GitLab CI / CircleCI) + Docker to run IvorySQL builds and tests in containers.
Minimal workflow (CI-friendly)
- Build or pull an IvorySQL Docker image in CI; start a server (initdb, pg_ctl start). Example: initdb -D /tmp/data && pg_ctl -D /tmp/data -o "-k /tmp" -w start. [2][3]
- Install test helpers:
- Install pgTAP extension into a test DB (CREATE EXTENSION pgtap), or add pgTAP SQL files to your repo. Use pg_prove to run TAP tests. [1]
- For server-level regression tests, run make installcheck or make installcheck-parallel after installing IvorySQL into the CI image. [2]
- Organize tests:
- Unit tests: write pgTAP tests that call your PL/SQL/PL/pgSQL functions. Use throws_ok() and lives_ok() to assert expected exceptions or successful execution. Use runtests() for xUnit-style test functions. [1]
- Integration tests: use SQL files and expected output by pg_regress (installcheck) for end-to-end behavior. [2]
- CI failure/error handling:
- Make CI fail on any non‑zero exit from pg_prove, make installcheck, or psql commands. Capture stdout/stderr and test TAP output as artifacts.
- Use pgTAP assertion functions to trap and assert error conditions (throws_ok for expected errors; lives_ok for code that must not raise). This gives clear TAP diagnostics for exception details. [1]
- If you run server-level regression tests, collect regression.diffs and server logs (pg_log) on failure. [2]
- Recommended CI steps (concise example)
- Checkout code
- Build IvorySQL or pull image
- initdb; pg_ctl start
- createdb test && psql -d test -c "CREATE EXTENSION pgtap;"
- pg_prove --dbname=test tests/*.sql || exit 1
- make installcheck || (cat log/*.log && exit 1)
- pg_ctl stop
(Collect TAP output and server logs as CI artifacts.) [1][2][3]
Notes and pointers
- Use pgTAP’s throws_ok/lives_ok to assert and report exception content and context instead of parsing psql exit codes. That yields better, structured error info in CI. [1]
- Use installcheck / pg_regress for compatibility/regression tests that exercise server internals; run these in an isolated CI runner because they can create cluster-wide temporary objects. [2]
- IvorySQL-specific packaging or extensions (e.g., DocumentDB support) should be installed into the test cluster before running tests; treat IvorySQL as PostgreSQL-compatible for testing flows. [3]
Sources
- pgTAP documentation (unit testing and throws_ok/lives_ok). [1]
- PostgreSQL regression test docs (make installcheck, pg_regress behavior). [2]
- IvorySQL docs/articles showing IvorySQL as PostgreSQL-compatible (installation / extensions). [3]
If you want, I can:
- produce a ready-to-run GitHub Actions workflow (YAML) that builds IvorySQL, runs pgTAP and installcheck, and collects logs; or
- draft a sample pgTAP test showing throws_ok usage for a PL/SQL function.
🌐 Web query:
IvorySQL plisql autonomous transaction tests
💡 Result:
Here are resources and example test approaches for PL/iSQL / autonomous-transaction behaviour (IvorySQL docs + canonical Oracle semantics + examples from other PostgreSQL-compatible projects that implement autonomous transactions):
- IvorySQL PL/iSQL docs (PL/iSQL language reference). Use this as your IvorySQL feature/reference starting point. [1]
- Oracle AUTONOMOUS_TRANSACTION pragma (semantics you should test for: independent transaction, can COMMIT/ROLLBACK inside, parent suspended). [2]
- Example implementations / test patterns used by other PG-compatible projects:
- MogDB: example CREATE FUNCTION showing PRAGMA AUTONOMOUS_TRANSACTION and START TRANSACTION / COMMIT usage — good test template. [3]
- Tantor docs: autonomous-transaction examples (logging, commit inside autonomous block, visibility on rollback). [4]
- Liberatii Gateway: wrapper/dblink-based emulation and caveats (useful if IvorySQL does not natively support autonomous tx). [5]
Suggested minimal tests (adapt these to IvorySQL PL/iSQL syntax):
-
Logging commit survives outer rollback
- Create log table.
- Create a PL/iSQL function/procedure declared AUTONOMOUS (PRAGMA AUTONOMOUS_TRANSACTION or equivalent) that INSERTs into log and COMMITs.
- In a separate function start a transaction, call the autonomous logger, then RAISE an error / ROLLBACK the outer transaction. Assert log row persists.
-
Autonomous COMMIT/ROLLBACK control
- Autonomous routine performs INSERT then conditionally COMMIT or ROLLBACK; assert visibility according to choice.
-
Visibility and isolation
- Ensure autonomous tx does not see uncommitted outer changes; ensure outer does/doesn’t see autonomous commits depending on isolation semantics.
-
Trigger/call-stack interactions and errors
- Call autonomous routine from trigger / nested procedures; test deadlock/visibility/error behavior.
Useful links:
- IvorySQL PL/iSQL docs. [1]
- Oracle AUTONOMOUS_TRANSACTION reference. [2]
- MogDB autonomous-transaction example. [3]
- Tantor autonomous-transaction examples. [4]
- Liberatii autonomous-transaction emulation notes. [5]
If you want, I can:
- produce ready-to-run IvorySQL test SQL/PLiSQL scripts for the 4 tests above, or
- search the IvorySQL GitHub for any existing autonomous-transaction tests and link to them. Which would you prefer?
Error handling test uses commented psql metacommands incompatible with automated regression testing.
Lines 315–317 show \set ON_ERROR_STOP off/on (psql metacommands) commented out above a raw SELECT test_function_error(); call. PostgreSQL regression tests (pg_regress, used by IvorySQL) capture expected output and compare it deterministically; commented metacommands do not suppress errors, so this test will produce uncontrolled error output and cause the regression suite to fail. IvorySQL's recommended approach for error testing is pgTAP's throws_ok() function, which asserts and validates exceptions within the test harness.
Restructure this test to use pgTAP throws_ok() to explicitly validate the error, or if this is a standalone regression test, ensure the error output is captured in an .expected file for comparison.
|
I completely agree with your decision to go with Approach 1 (the dblink-based implementation). It requires less effort and is easier to maintain. Although the performance is somewhat lower. |
| proc_name, | ||
| args.data); | ||
| } | ||
|
|
There was a problem hiding this comment.
Given that we consistently set plisql.inside_autonomous_transaction = true, is this GUC truly necessary?
There was a problem hiding this comment.
Yes, the GUC is necessary to prevent infinite recursion. When an autonomous function executes via dblink, the GUC is set to true in that session. If the function then calls another autonomous function (or itself), the check at pl_exec.c:696:
if (func->fn_is_autonomous &&
!plisql_inside_autonomous_transaction && // skips dblink if already inside
...)
prevents spawning another dblink connection. Instead, the nested call executes directly within the existing autonomous session.
Without this GUC, nested autonomous calls would create recursive dblink connections.
There was a problem hiding this comment.
Clear, thank you for the clarification.
There was a problem hiding this comment.
@rophy
I'm trying to test it manually, and see that it requires feature allow COMMIT/ROLLBACK in nested PL/iSQL procedure calls , correct?
pl_exec.c:696:
if (func->fn_is_autonomous &&
!plisql_inside_autonomous_transaction && // skips dblink if already inside
...)
There was a problem hiding this comment.
hmm, I think they're relevant, but different issues?
There was a problem hiding this comment.
sure, it's absolutely another feature
|
Considering that both Meson and Make build systems are supported, could you please add 'pl_autonomous.c'to the meson.build file? |
- Add Test 21: autonomous transaction in package procedure - Add pl_autonomous.c to meson.build for Meson build support
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/pl/plisql/src/sql/plisql_autonomous.sql (1)
301-317: Error handling test produces uncontrolled error output; incompatible with regression testing.Lines 315–317 show
\set ON_ERROR_STOP off/on(psql metacommands) commented out above aSELECT test_function_error();call. In PostgreSQL regression tests (pg_regress, used by IvorySQL), error output must be deterministic and captured in a corresponding.expectedfile. The commented metacommands do not suppress errors, so this test will produce unhandled failure output and cause the regression suite to fail.Options:
- Create a separate
plisql_autonomous.expectedfile with the expected error output for this test, or- Use pgTAP's
throws_ok()function to explicitly validate the exception within a proper test harness, or- Move error handling tests to a separate test file with dedicated error-output handling.
Verify which approach is used by other PL/iSQL tests in the repository (e.g., check
src/pl/plisql/src/sql/for.expectedfiles or pgTAP usage patterns).
🧹 Nitpick comments (2)
src/pl/plisql/src/sql/plisql_autonomous.sql (2)
29-29: Remove unnecessary COMMIT statements after DDL blocks.Multiple COMMIT statements appear immediately after procedure/function creation and before the next test block (e.g., lines 29, 45, 61). These are not required in SQL scripts; DDL auto-commits and explicit COMMITs between statements are unnecessary. They add noise and clutter the test file.
Remove these standalone COMMIT statements throughout the file. PostgreSQL/IvorySQL will auto-commit DDL without explicit COMMIT directives in batch SQL mode.
Also applies to: 45-45, 61-61, 92-92, 108-108, 124-124, 153-153, 179-179, 209-209, 230-230, 312-312, 334-334, 363-363, 384-384, 404-404, 425-425, 449-449
185-189: Destructive test: dropping and recreating dblink during test execution.This test (lines 185–189) deliberately drops the dblink extension to verify OID invalidation, then immediately recreates it. While the feature is important to test, dropping a required extension mid-test could corrupt the test environment or cause subsequent tests to fail if execution order changes or if cleanup is interrupted. Consider:
- Running this test in an isolated transaction or separate test session, or
- Using a mock/synthetic method to test OID invalidation without destructively dropping the extension, or
- Documenting this as a known risk and ensuring it runs last in the test sequence.
Document the destructive nature of this test, or isolate it in a separate test file to prevent unintended side effects.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/pl/plisql/src/expected/plisql_autonomous.outis excluded by!**/*.out
📒 Files selected for processing (2)
src/pl/plisql/src/meson.build(1 hunks)src/pl/plisql/src/sql/plisql_autonomous.sql(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-03T06:50:27.755Z
Learnt from: rophy
Repo: IvorySQL/IvorySQL PR: 998
File: contrib/ivorysql_ora/src/builtin_packages/dbms_output/dbms_output.c:82-146
Timestamp: 2025-12-03T06:50:27.755Z
Learning: In contrib/ivorysql_ora/src/builtin_packages/dbms_output/dbms_output.c, the behavior where ENABLE() clears the existing buffer (rather than preserving it like Oracle does) is an intentional known difference tracked in issue #26 at https://github.com/rophy/IvorySQL/issues/26 (medium impact, open).
Applied to files:
src/pl/plisql/src/sql/plisql_autonomous.sql
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: oracle_regression (ubuntu-latest)
- GitHub Check: pg_regression (ubuntu-latest)
- GitHub Check: meson_build (ubuntu-latest)
- GitHub Check: oracle_pg_regression (ubuntu-latest)
- GitHub Check: contrib_regression
- GitHub Check: build (ubuntu-latest)
🔇 Additional comments (6)
src/pl/plisql/src/meson.build (1)
13-13: pl_autonomous.c correctly wired into buildAdding
'pl_autonomous.c'toplisql_sourcesensures the autonomous-transaction support is compiled into theplisqlshared module and aligns with the prior review request to hook this file into Meson. No further Meson changes seem necessary here.src/pl/plisql/src/sql/plisql_autonomous.sql (5)
435-452: Package procedure test case correctly added.The package procedure test (lines 435–452) addresses OreoYang's request and properly validates autonomous transaction behavior within package-body routines. The test follows the same pattern as standalone procedures and verifies both the autonomous execution and data persistence.
236-296: Commented-out COMMIT/ROLLBACK tests provide good documentation of known limitations.Tests 12–14 (lines 236–296) are correctly commented out and reference Issue #985, clearly documenting that explicit COMMIT/ROLLBACK within autonomous blocks is not yet supported in PL/iSQL. The comments explain the expected failure mode and set appropriate expectations for future enhancements.
1-15: Test setup and schema are well structured.The setup correctly installs dblink, creates a focused test table (autonomous_test) with three columns (id, msg, tx_state), and uses clear comments to separate test sections. This design facilitates debugging and future expansion.
340-367: Nested autonomous function test effectively validates SPI context handling.The nested autonomous test (inner_function and outer_function, lines 340–367) correctly exercises multiple SPI contexts and verifies that both outer and inner autonomous calls execute and commit independently. The expected result (id=60 outer, id=160 inner, return value 175) demonstrates proper isolation and value propagation across nested calls.
197-197: The syntax is correct for PL/iSQL. IvorySQL's PL/iSQL dialect usesRETURN type(notRETURNS type) to match Oracle PL/SQL compatibility. This is intentional and consistent with the Oracle-compatible design of the test suite.
added |
Autonomous Transaction Limitations (dblink-based implementation)IvorySQL implements Limitations1. Cannot call private package proceduresFile: CREATE OR REPLACE PACKAGE BODY my_pkg AS
PROCEDURE private_helper IS ... END; --
Not in package spec
PROCEDURE autonomous_proc IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
private_helper; -- ERROR: doesn't exist in package
END;
END;Error: 2. Cannot access package stateFile: CREATE OR REPLACE PACKAGE BODY my_pkg AS
g_counter NUMBER := 0; -- Package variable
PROCEDURE log_msg IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
g_counter := g_counter + 1; -- Sees 0, not caller's value
other_pkg_proc(); -- May fail with subtransaction error
END;
END;Issues:
Root Causedblink opens a new database session:
What Works
NoteEDB Postgres Advanced Server has the same limitations despite using background workers instead of dblink - the fundamental issue |
|
As a matter of fact, this dblink-based implementation is somewhat limited in terms of enabling oracle packages to run autonomous transactions. While it works for simple cases, it failed in enabling my sample oracle package to work, at least not without refactoring. |
Thanks for your update, I'll share your design implementation internally next week. |
Yes, I see it in your posted references, aws and ora2pg select the same design. |
|
For the record, Tom Lane also recommends using dblink to implement autonomous transactions. https://www.postgresql.org/message-id/1830668.1742655550%40sss.pgh.pa.us |
Summary
This PR implements Oracle-compatible PRAGMA AUTONOMOUS_TRANSACTION syntax for PL/iSQL, enabling functions and procedures to execute in independent transactions that can commit or rollback separately from the parent transaction.
Implementation Approach
Design Decision: dblink-based Implementation
After evaluating three approaches, we chose a dblink-based implementation for the initial release:
Approach 1: dblink Extension (Chosen)
How it works: Opens new database connection for independent transaction
Pros:
Cons:
References:
Approach 2: pg_background Extension (Evaluated but not chosen)
How it works: Uses background worker processes for independent transactions
Pros:
Cons:
References:
Approach 3: Native PostgreSQL Patch (Future consideration)
How it works: Port WIP PostgreSQL autonomous transaction patch
Status: Work in Progress (not merged to PostgreSQL upstream as of December 2023)
Pros:
Cons:
References:
Decision Rationale
I chose Approach 1 (dblink) because:
Syntax
Supported declarations:
Placement: Must appear in DECLARE section (anywhere among variable declarations)
Implementation Details
Recursion Prevention
Autonomous transactions are prevented from recursively calling themselves via a session-local GUC flag:
Why PGC_USERSET instead of PGC_INTERNAL:
dblinkin a separate connectionSET plisql.inside_autonomous_transaction = true;PGC_INTERNAL, PostgreSQL silently ignores the SET commandSecurity mitigation:
SHOW ALLviaGUC_NO_SHOW_ALLGUC_NOT_IN_SAMPLERESET ALLviaGUC_NO_RESET_ALLOID Cache Invalidation
The implementation caches the
dblink_execfunction OID for performance. A syscache invalidation callback ensures the cache is cleared when the dblink extension is dropped/recreated:Connection String Safety
The implementation uses proper libpq connection string escaping (single-quote escaping) instead of SQL identifier quoting (double-quote escaping):
NULL Safety
Guards against
get_namespace_name()returning NULL when a schema is dropped concurrently:Deployment Requirements
Installation
Install dblink extension (one-time per database):
Usage (no additional configuration needed):
Configuration
No special configuration required. The implementation automatically:
portfrom GUC settingslisten_addressesfrom GUC settingsKnown Limitations
COMMIT/ROLLBACK not supported in autonomous blocks (Issue PL/iSQL does not support COMMIT/ROLLBACK in procedures (Oracle compatibility gap) #985)
ERROR: invalid transaction terminationRequires dblink extension
CREATE EXTENSION dblinkConnection overhead
No nested savepoint support
Performance overhead for pass-by-reference types
Security Considerations
GUC flag (
plisql.inside_autonomous_transaction)dblink permissions
SQL injection protection
quote_literal_cstr()Oracle Compatibility
Matches Oracle Behavior
✅ Syntax:
PRAGMA AUTONOMOUS_TRANSACTIONin DECLARE section✅ Transaction isolation: Autonomous commits/rollbacks are independent
✅ Use cases: Logging, auditing, error tracking work as expected
✅ Recursion prevention: Autonomous routines cannot call themselves
✅ Exception handling: Exceptions in autonomous blocks don't affect parent
✅ Function return values: Full support for all PostgreSQL types (INT, TEXT, NUMERIC, DATE, BOOLEAN, etc.)
✅ Nested autonomous calls: Autonomous functions can call other autonomous functions
✅ Error handling: Proper cleanup via PG_TRY/PG_CATCH ensures no memory leaks
Known Differences from Oracle
Test Coverage (20 tests)
17-20. COMMIT/ROLLBACK tests (commented, ref Issue PL/iSQL does not support COMMIT/ROLLBACK in procedures (Oracle compatibility gap) #985)
Summary by CodeRabbit
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.