Skip to content

fix(plpgsql): bump @libpg-query/parser to 17.8.0 + OUT-param RETURN NEXT, EXCEPTION wrapper block, and comment-reinjection fixes#307

Merged
pyramation merged 4 commits into
mainfrom
fix/plpgsql-out-param-varno
Jul 21, 2026
Merged

fix(plpgsql): bump @libpg-query/parser to 17.8.0 + OUT-param RETURN NEXT, EXCEPTION wrapper block, and comment-reinjection fixes#307
pyramation merged 4 commits into
mainfrom
fix/plpgsql-out-param-varno

Conversation

@pyramation

Copy link
Copy Markdown
Collaborator

Summary

Bumps @libpg-query/parser to ^17.8.0 (built from constructive-io/libpg_query@17-constructive, which now serializes retvarno and out_param_varno) and fixes the deparser bugs that surface once those fields — and a single unified WASM instance — actually flow through the stack.

1. plpgsql-deparser: keep RETURN NEXT bare when retvarno targets the OUT parameters

With retvarno now emitted by the parser, RETURN NEXT; in an OUT-param function would deparse as RETURN NEXT x — invalid SQL (with OUT params it must stay bare). The deparser now threads func.out_param_varno through the context:

if (ret.retvarno >= 0 && ret.retvarno !== context.outParamVarno) emit `RETURN NEXT ${varName}`
else emit `RETURN NEXT`

Same rule applied to implicit-final-RETURN stripping. Fixtures 57–58.

2. plpgsql-deparser: unwrap the compiler-generated EXCEPTION wrapper block

When a function's top-level block has an EXCEPTION clause, the PL/pgSQL compiler wraps it in a synthetic outer block (no lineno) whose body is just the user's block + implicit return. Deparsing that verbatim emitted a redundant BEGIN BEGIN … END; END. deparseFunction now unwraps via unwrapCompilerWrapperBlock: only when the outer block has no lineno, no label, no exceptions, and exactly one PLpgSQL_stmt_block child — so explicit user-written nested blocks (which carry a lineno) are preserved. Fixtures 59–60 cover both cases.

3. plpgsql-parse: comment-reinjection fixes

The comment-preserving deparse path in plpgsql-parse had never actually executed: the workspace previously resolved two @libpg-query/parser instances (^17.6.10 in plpgsql-parse vs ^17.6.3 in plpgsql-deparser), so hydration always threw "WASM not initialized" into the silent fallback (Deparser.deparse of the raw statement, which prints the original body verbatim). The old snapshots captured that fallback. With one unified version the path runs for real, exposing two bugs now fixed:

  • stitchBodyIntoAst pads the rebuilt body with newlines so output is AS $$\n<body>\n$$ instead of AS $$DECLARE…
  • the keyword-matching walker in reinjectBodyComments now skips DECLARE sections, so a declaration like v_x int; no longer consumes the keyword match for a later v_x := … assignment (which misplaced comments on the first pass and dropped them on the second — the idempotency failure)

Snapshots regenerated to the real enhanced output; all fixture round-trips are idempotent.

Test results

deparser 713, transform 1126, plpgsql-deparser 106, plpgsql-parser 285, plpgsql-parse 57, parse 68, parser 9, quotes 57, traverse 12, utils 4, proto-parser 42 — all passing against the published @libpg-query/parser@17.8.0.

Note: pnpm-lock.yaml has large formatting churn from lockfile regeneration (quote style); the substantive change is only the parser version.

Link to Devin session: https://app.devin.ai/sessions/eeb8deba0c04475091df703c88877302
Requested by: @pyramation

…e function's OUT parameters

libpg-query now emits retvarno and out_param_varno in the PL/pgSQL JSON.
With OUT parameters, RETURN NEXT must stay bare (PostgreSQL rejects an
expression there), so suppress the variable when retvarno equals
out_param_varno; likewise treat the compiler's implicit final RETURN
(retvarno == out_param_varno) as implicit.
…h newlines, skip DECLARE sections during statement matching
@pyramation pyramation self-assigned this Jul 21, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​libpg-query/​parser@​17.8.07510010090100

View full report

@pyramation
pyramation merged commit 50d90ab into main Jul 21, 2026
9 checks passed
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.

1 participant