Skip to content

support function and procedure in WITH clause#1322

Open
bigplaice wants to merge 8 commits into
IvorySQL:masterfrom
bigplaice:with_func_proc
Open

support function and procedure in WITH clause#1322
bigplaice wants to merge 8 commits into
IvorySQL:masterfrom
bigplaice:with_func_proc

Conversation

@bigplaice
Copy link
Copy Markdown
Collaborator

@bigplaice bigplaice commented May 7, 2026

fix #1067

Summary by CodeRabbit

  • New Features

    • Oracle-style WITH FUNCTION/PROCEDURE support inside queries; inline subprograms with parameters, defaults, recursion, and exception handling.
    • EXPLAIN shows WITH-function/procedure signatures and, in verbose mode, includes function bodies.
  • Behavior Changes

    • WITH functions are preserved through planning into execution and EXPLAIN.
    • WITH functions are restricted to scalar-expression contexts and will error if used as table/set-returning functions.
  • Tests

    • Added comprehensive regression tests covering positive, negative, DML, and EXPLAIN scenarios.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Implements Oracle-style WITH FUNCTION/PROCEDURE support: grammar and lexer, parse-time registration and call-site hook, propagation into Query/PlannedStmt, planner/EXPLAIN printing, executor/fmgr guards, PL/iSQL lazy compilation and runtime dispatch, build updates, and regression tests.

Changes

WITH Clause Inline Functions and Procedures

Layer / File(s) Summary
Grammar and frontend lexer
src/backend/oracle_parser/ora_gram.y, src/oracle_fe_utils/ora_psqlscan.l, src/backend/commands/explain.c
Bison grammar additions and lexer rule changes parse WITH FUNCTION/PROCEDURE blocks and semicolon/END contexts; EXPLAIN includes new printing of WITH subprogram signatures/bodies.
Parse-time registration & lookup
src/backend/parser/parse_with_plsql.c, src/backend/parser/parse_func.c, src/backend/parser/parse_cte.c, src/backend/parser/parse_clause.c, src/include/parser/parse_node.h
transformWithFuncDefs registers inline defs, enforces IN-only params, pre-analyzes defaults, records metadata into ParseState, installs withFuncLookupHook, and provides ancestor lookup fallback for nested/recursive calls.
Transform → Query → PlannedStmt propagation
src/backend/parser/analyze.c, src/backend/parser/parse_merge.c, src/include/nodes/parsenodes.h, src/include/nodes/plannodes.h
With-clause plsql_defs are propagated into Query.withFuncDefs for many statement kinds and copied into PlannedStmt.withFuncDefs; new InlineFunctionDef node added.
Planner and EXPLAIN integration
src/backend/optimizer/plan/planner.c, src/backend/commands/explain.c
PlannedStmt carries withFuncDefs; ExplainPrintWithFunctions added and invoked to print WITH inline subprogram signatures and bodies (verbose).
Executor, fmgr, SRF/type guards
src/backend/executor/execExpr.c, src/backend/executor/execSRF.c, src/backend/executor/execTuples.c, src/backend/utils/fmgr/funcapi.c, src/include/nodes/execnodes.h, src/include/nodes/primnodes.h
Executor detects FUNC_FROM_WITH_CLAUSE, initializes fmgr subproc context with correct EState, skips OUT-parameter handling for WITH funcs, rejects WITH funcs as table/SRF functions, and adds FUNC_FROM_WITH_CLAUSE discriminator and EState container pointer.
PL/iSQL compile & runtime dispatch
src/pl/plisql/src/pl_comp.c, src/pl/plisql/src/pl_handler.c, src/pl/plisql/src/plisql.h
PL/iSQL lazily compiles WITH inline functions into a per-query WithFuncContainer, fixes compiled return/prokind metadata, tracks active WITH entries/estate for recursion, and updates plisql_compile_inline usage.
Headers, build files
src/include/oracle_parser/ora_with_function.h, src/backend/parser/Makefile, src/backend/parser/meson.build
New public header for cross-phase APIs and types; parser build lists updated to compile the new parse module.
Regression tests & schedule
src/oracle_test/regress/sql/with_function.sql, src/oracle_test/regress/expected/with_function*.out, src/oracle_test/regress/parallel_schedule
Comprehensive positive and negative tests for WITH FUNCTION/PROCEDURE usage, EXPLAIN assertions, and schedule entries added.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • IvorySQL/IvorySQL#945: Both PRs modify OUT-parameter and subproc handling paths; overlap in executor/parse logic.
  • IvorySQL/IvorySQL#944: Overlapping edits touching OUT-parameter plumbing and executor initialization for special function origins.

Suggested reviewers

  • OreoYang
  • jiaoshuntian
  • NotHimmel

"🐰 I stitched inline functions in WITH so neat,
From parse to plan, their journey's complete,
Lexer, EXPLAIN, PLiSQL all in tow—
This rabbit hops proudly — the feature will show! 🥕"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'support function and procedure in WITH clause' directly describes the main feature being implemented, which is enabling functions and procedures to be declared within SQL WITH clauses.
Linked Issues check ✅ Passed The PR comprehensively implements the feature requested in #1067: it enables WITH clause to declare and use procedures and functions within SQL queries across all relevant code paths (parsing, semantic analysis, planning, execution, and EXPLAIN output).
Out of Scope Changes check ✅ Passed All changes are directly related to implementing WITH clause function/procedure support: grammar updates, parser enhancements, query transformation, execution handling, EXPLAIN display, and comprehensive test coverage. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 81.58% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/backend/parser/analyze.c (1)

380-382: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

withFuncDefs is not propagated for MERGE statements.

The default transformMergeStmt implementation in src/backend/parser/parse_merge.c (lines 124–132) calls transformWithClause and sets qry->hasModifyingCTE, but omits the assignment qry->withFuncDefs = stmt->withClause->plsql_defs. All other DML transformers (INSERT, UPDATE, DELETE, VALUES, set-ops) perform this assignment. Without it, WITH FUNCTION … MERGE … will silently discard inline function definitions. The Oracle hook implementation correctly includes this assignment (see contrib/ivorysql_ora/src/merge/ora_merge.c line 701), indicating it should be in the standard implementation as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/parser/analyze.c` around lines 380 - 382, The MERGE transformer
is not propagating WITH FUNCTION definitions: update the default
transformMergeStmt implementation to call transformWithClause (as it already
does) and then assign qry->withFuncDefs = stmt->withClause->plsql_defs (and
preserve existing qry->hasModifyingCTE behavior) so that inline function defs
from stmt->withClause are propagated into the resulting Query; modify
transformMergeStmt to mirror the withFuncDefs assignment used by other DML
transformers (and by the Oracle hook implementation) to ensure WITH FUNCTION …
MERGE … retains the definitions.
src/include/nodes/parsenodes.h (1)

1662-1663: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the WithClause propagation comment to match current behavior.

The comment says WithClause does not propagate into Query, but Query.withFuncDefs now carries data derived from it. This is misleading for future maintainers.

Also applies to: 1668-1668

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/include/nodes/parsenodes.h` around lines 1662 - 1663, The existing
comment claiming "WithClause does not propagate into the Query" is outdated;
change the comment(s) around WithClause (both occurrences) to state that
WithClause-derived information is now carried into Query via Query.withFuncDefs
(and that CommonTableExpr still propagates as before), so future readers
understand that Query.withFuncDefs holds data derived from WithClause.
🧹 Nitpick comments (5)
src/backend/executor/execSRF.c (1)

156-157: 💤 Low value

Silent skip at line 157 is consistent with the init_sexpr error barrier — but consider an explicit Assert.

The funcexpr->function_from != FUNC_FROM_WITH_CLAUSE guard prevents subproc_should_change_return_type from being called on a WITH-clause function. In practice this code path is unreachable because init_sexpr (called earlier, during ExecInitTableFunctionResult) would have already raised an error. The current behaviour — silently falling through to the outer funcrettype = exprType(...) — is harmless given that guarantee.

However, adding Assert(funcexpr->function_from != FUNC_FROM_WITH_CLAUSE) immediately before line 158 would make the invariant explicit and catch any future regression during development.

🛡️ Optional: make the invariant explicit
  else if (!FUNC_EXPR_FROM_PG_PROC(funcexpr->function_from) &&
+          /* WITH-clause functions must have been rejected by init_sexpr already */
+          Assert(funcexpr->function_from != FUNC_FROM_WITH_CLAUSE),
           funcexpr->function_from != FUNC_FROM_WITH_CLAUSE &&
           subproc_should_change_return_type(funcexpr,
                                             &resulttype,
                                             &chtypmod,
                                             &chcollationoid))

(Alternatively, a standalone Assert statement placed before the else if would read more clearly.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/executor/execSRF.c` around lines 156 - 157, Add an explicit
Assert to document the invariant that a WITH-clause function cannot reach this
branch: before the else-if that checks funcexpr->function_from (the block that
currently skips calling subproc_should_change_return_type and falls back to
computing funcrettype via exprType), insert Assert(funcexpr->function_from !=
FUNC_FROM_WITH_CLAUSE). This makes the guarantee from init_sexpr (invoked during
ExecInitTableFunctionResult) explicit and will catch regressions where a
WITH-clause function could reach this code path.
src/oracle_test/regress/sql/with_function.sql (2)

22-28: ⚡ Quick win

Add a sibling-call case from inside a WITH subprogram body.

Current coverage proves top-level composition and self-recursion, but not the new path where one inline subprogram resolves a sibling WITH function/procedure from inside its own body. That is the exact scope-propagation path added in this PR, so it should have a regression. As per coding guidelines, **/sql/*.sql: Test SQL files. Ensure comprehensive coverage of features.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oracle_test/regress/sql/with_function.sql` around lines 22 - 28, Add a
new test in the WITH-function regression file that exercises a sibling-call from
inside a WITH subprogram body: create two WITH FUNCTIONS (e.g., add1 and mul2 as
in the diff) but modify one function body so it calls its sibling (for example,
have mul2 call add1 internally or vice versa) and then SELECT the top-level call
to exercise the new scope propagation path; ensure the test lives alongside the
existing WITH FUNCTION examples in src/oracle_test/regress/sql/with_function.sql
and uses the same function names (add1, mul2) so the test covers resolving a
sibling WITH function from inside a subprogram body.

8-13: ⚡ Quick win

Add a regression that actually invokes a WITH PROCEDURE.

This only proves the declaration parses. It never exercises the procedure execution path, argument binding, or side effects, so a break in the new runtime support could still pass this file. As per coding guidelines, **/sql/*.sql: Test SQL files. Ensure comprehensive coverage of features.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oracle_test/regress/sql/with_function.sql` around lines 8 - 13, The file
only declares the WITH PROCEDURE do_nothing without invoking it; update the test
to actually execute the procedure (e.g., add a CALL do_nothing; or a BEGIN
do_nothing; END; block) and then assert a side-effect or result (keep the
existing SELECT 'procedure ok' AS result or replace with a SELECT that verifies
the side-effect) so the runtime execution, argument binding and side-effect path
for the WITH PROCEDURE named do_nothing is exercised.
src/oracle_test/regress/expected/with_function.out (2)

11-20: ⚡ Quick win

T02 does not validate actual WITH PROCEDURE invocation.

This case currently proves parsing/acceptance, but not procedure execution semantics. Please add one case that invokes the procedure (directly or via a WITH function wrapper) and asserts an observable effect.

As per coding guidelines, **/expected/*.out files must cover Oracle-compatibility behavior and edge-case coverage, and the referenced contract requires side-effect/void-style WITH PROCEDURE semantics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oracle_test/regress/expected/with_function.out` around lines 11 - 20, The
test defines WITH PROCEDURE do_nothing but never invokes it; update the test to
actually call the procedure and assert a side-effect-observable result by adding
a WITH-function wrapper that invokes do_nothing and returns a marker (e.g., a
function call_wrapper that calls do_nothing then returns 'procedure ok'), then
SELECT the wrapper result so the output verifies execution semantics of WITH
PROCEDURE (reference symbols: WITH PROCEDURE do_nothing and the new wrapper
function name you add).

351-363: ⚡ Quick win

Add EXPLAIN VERBOSE coverage for WITH PROCEDURE body text.

You already verify function body rendering in VERBOSE mode; add the equivalent procedure-body assertion to lock that part of the EXPLAIN contract too.

As per coding guidelines, **/expected/*.out files must ensure edge-case coverage, and the referenced contract requires EXPLAIN output coverage for WITH Function/Procedure definitions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oracle_test/regress/expected/with_function.out` around lines 351 - 363,
Add a second EXPLAIN VERBOSE case mirroring the existing FUNCTION block: after
the EXPLAIN (COSTS OFF, VERBOSE) test that exercises WITH FUNCTION shows_body,
add an analogous EXPLAIN that defines a WITH PROCEDURE (e.g., WITH PROCEDURE
shows_proc(...) IS ... END;) and selects/calls it so the verbose output includes
a "WITH Procedure: shows_proc" line and a "Body: ..." line; update the expected
output block to assert those Procedure lines just like the Function ones so
EXPLAIN VERBOSE covers WITH PROCEDURE body text.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/backend/parser/parse_cte.c`:
- Around line 129-132: The errhint currently references the C enum constant
ORA_PARSER which users cannot type; update the errhint in the ereport call (the
block using ereport/errcode/errmsg/errhint) to instruct users to set the GUC to
the user-typable string value by changing the hint text to: "Set
ivorysql.compatible_mode = 'oracle' to enable this feature." Keep the rest of
the ereport invocation unchanged.

In `@src/backend/parser/parse_with_plsql.c`:
- Around line 249-309: The current check uses (nentryargs - nargs) >
entry->ndefaults which only counts defaults, not whether the omitted suffix is
fully defaulted; change the validation to ensure every omitted parameter
(positions from nargs to nentryargs-1) is a defaulted trailing parameter by
scanning entry->argtypes/entry->analyzeddefaults from the end and counting
contiguous trailing defaults and rejecting the call if omitted_count >
trailing_defaults; also only append analyzeddefaults into *fargs when the
expansion flag (expand_defaults) is true (and remove/avoid hitting Assert by
ensuring we never iterate into non-default params).

In `@src/pl/plisql/src/pl_handler.c`:
- Around line 349-385: buildWithFuncEntries creates WithFuncEntry objects but
never initializes their default-argument metadata, causing garbage reads later;
update buildWithFuncEntries to initialize the default-related fields on each new
WithFuncEntry (match how transformWithFuncDefs sets up defaults) — at minimum
set entry->ndefaults = 0 and entry->analyzeddefaults = NULL (or the appropriate
zero/empty values for those fields) and ensure any flag or mechanism that
triggers default expansion for runtime calls is disabled unless defaults are
properly analyzed; reference buildWithFuncEntries, WithFuncEntry,
p_with_func_list and transformWithFuncDefs to copy the same
initialization/behavior for default handling.
- Around line 287-337: buildParamListForFunc() currently omits FUNC_PARAM_OUT
entries (and returns NULL if nparams==0), which means OUT-only parameters never
get a variable in the compiled WITH subprogram; to fix, count and allocate
ParamListInfo entries for OUT parameters as well (i.e., include fp->mode ==
FUNC_PARAM_OUT when computing nparams), and in the second loop do not skip OUT
params—resolve their type with typenameTypeIdAndMod and populate paramnames and
params[*] (ptype, ptypmod, pmode as (char)fp->mode, isnull/value as appropriate)
so OUT params exist in the resulting ParamListInfo used by
plisql_compile_inline().

---

Outside diff comments:
In `@src/backend/parser/analyze.c`:
- Around line 380-382: The MERGE transformer is not propagating WITH FUNCTION
definitions: update the default transformMergeStmt implementation to call
transformWithClause (as it already does) and then assign qry->withFuncDefs =
stmt->withClause->plsql_defs (and preserve existing qry->hasModifyingCTE
behavior) so that inline function defs from stmt->withClause are propagated into
the resulting Query; modify transformMergeStmt to mirror the withFuncDefs
assignment used by other DML transformers (and by the Oracle hook
implementation) to ensure WITH FUNCTION … MERGE … retains the definitions.

In `@src/include/nodes/parsenodes.h`:
- Around line 1662-1663: The existing comment claiming "WithClause does not
propagate into the Query" is outdated; change the comment(s) around WithClause
(both occurrences) to state that WithClause-derived information is now carried
into Query via Query.withFuncDefs (and that CommonTableExpr still propagates as
before), so future readers understand that Query.withFuncDefs holds data derived
from WithClause.

---

Nitpick comments:
In `@src/backend/executor/execSRF.c`:
- Around line 156-157: Add an explicit Assert to document the invariant that a
WITH-clause function cannot reach this branch: before the else-if that checks
funcexpr->function_from (the block that currently skips calling
subproc_should_change_return_type and falls back to computing funcrettype via
exprType), insert Assert(funcexpr->function_from != FUNC_FROM_WITH_CLAUSE). This
makes the guarantee from init_sexpr (invoked during ExecInitTableFunctionResult)
explicit and will catch regressions where a WITH-clause function could reach
this code path.

In `@src/oracle_test/regress/expected/with_function.out`:
- Around line 11-20: The test defines WITH PROCEDURE do_nothing but never
invokes it; update the test to actually call the procedure and assert a
side-effect-observable result by adding a WITH-function wrapper that invokes
do_nothing and returns a marker (e.g., a function call_wrapper that calls
do_nothing then returns 'procedure ok'), then SELECT the wrapper result so the
output verifies execution semantics of WITH PROCEDURE (reference symbols: WITH
PROCEDURE do_nothing and the new wrapper function name you add).
- Around line 351-363: Add a second EXPLAIN VERBOSE case mirroring the existing
FUNCTION block: after the EXPLAIN (COSTS OFF, VERBOSE) test that exercises WITH
FUNCTION shows_body, add an analogous EXPLAIN that defines a WITH PROCEDURE
(e.g., WITH PROCEDURE shows_proc(...) IS ... END;) and selects/calls it so the
verbose output includes a "WITH Procedure: shows_proc" line and a "Body: ..."
line; update the expected output block to assert those Procedure lines just like
the Function ones so EXPLAIN VERBOSE covers WITH PROCEDURE body text.

In `@src/oracle_test/regress/sql/with_function.sql`:
- Around line 22-28: Add a new test in the WITH-function regression file that
exercises a sibling-call from inside a WITH subprogram body: create two WITH
FUNCTIONS (e.g., add1 and mul2 as in the diff) but modify one function body so
it calls its sibling (for example, have mul2 call add1 internally or vice versa)
and then SELECT the top-level call to exercise the new scope propagation path;
ensure the test lives alongside the existing WITH FUNCTION examples in
src/oracle_test/regress/sql/with_function.sql and uses the same function names
(add1, mul2) so the test covers resolving a sibling WITH function from inside a
subprogram body.
- Around line 8-13: The file only declares the WITH PROCEDURE do_nothing without
invoking it; update the test to actually execute the procedure (e.g., add a CALL
do_nothing; or a BEGIN do_nothing; END; block) and then assert a side-effect or
result (keep the existing SELECT 'procedure ok' AS result or replace with a
SELECT that verifies the side-effect) so the runtime execution, argument binding
and side-effect path for the WITH PROCEDURE named do_nothing is exercised.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 255887cf-561f-450c-9f33-cf6a3814d96f

📥 Commits

Reviewing files that changed from the base of the PR and between 35e086c and c709873.

📒 Files selected for processing (28)
  • contrib/ivorysql_ora/src/merge/ora_merge.c
  • src/backend/commands/explain.c
  • src/backend/executor/execExpr.c
  • src/backend/executor/execSRF.c
  • src/backend/executor/execTuples.c
  • src/backend/optimizer/plan/planner.c
  • src/backend/oracle_parser/ora_gram.y
  • src/backend/parser/Makefile
  • src/backend/parser/analyze.c
  • src/backend/parser/meson.build
  • src/backend/parser/parse_clause.c
  • src/backend/parser/parse_cte.c
  • src/backend/parser/parse_func.c
  • src/backend/parser/parse_with_plsql.c
  • src/backend/utils/fmgr/funcapi.c
  • src/include/nodes/execnodes.h
  • src/include/nodes/parsenodes.h
  • src/include/nodes/plannodes.h
  • src/include/nodes/primnodes.h
  • src/include/oracle_parser/ora_with_function.h
  • src/include/parser/parse_node.h
  • src/oracle_fe_utils/ora_psqlscan.l
  • src/oracle_test/regress/expected/with_function.out
  • src/oracle_test/regress/parallel_schedule
  • src/oracle_test/regress/sql/with_function.sql
  • src/pl/plisql/src/pl_comp.c
  • src/pl/plisql/src/pl_handler.c
  • src/pl/plisql/src/plisql.h

Comment thread src/backend/parser/parse_cte.c Outdated
Comment thread src/backend/parser/parse_with_plsql.c Outdated
Comment thread src/pl/plisql/src/pl_handler.c
Comment thread src/pl/plisql/src/pl_handler.c
bigplaice and others added 7 commits May 8, 2026 01:01
In Oracle, documented single-row SQL functions (ABS, ROUND, SUBSTR, ...)
are always resolved before any query-local definition; a WITH FUNCTION
of the same name is silently bypassed.

Previously withFuncLookupHook was called before func_get_detail, so
WITH FUNCTION abs(...) would intercept abs(-5) and return 999 instead
of the expected 5.

Add an Oracle SQL built-in name whitelist in withFuncLookupHook. When
the called function name is on the whitelist and pg_catalog has a
matching candidate, the hook returns FUNCDETAIL_NOTFOUND so that the
normal catalog path resolves the call. PostgreSQL-specific catalog
entries absent from the whitelist (e.g. factorial) remain overridable
by WITH FUNCTION.

This is a temporary bridge; once IvorySQL implements the STANDARD
package, LookupPkgFunc("standard.name") will win in ParseFuncOrColumn
before this hook is reached, making the whitelist redundant.

Update test T18 expected output from 999 to 5 to match Oracle behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

oracle compatibility feature: WITH clause supports procedures and functions

1 participant