Skip to content

feat: PostgreSQL 18 support (libpg-query 18.1.1, @pgsql/types 18)#309

Merged
pyramation merged 3 commits into
mainfrom
feat/pg18-support
Jul 21, 2026
Merged

feat: PostgreSQL 18 support (libpg-query 18.1.1, @pgsql/types 18)#309
pyramation merged 3 commits into
mainfrom
feat/pg18-support

Conversation

@pyramation

Copy link
Copy Markdown
Collaborator

Summary

Upgrades the whole monorepo to PostgreSQL 18: libpg-query@18.1.1 + @pgsql/types@^18.0.0 everywhere (SQL side and PL/pgSQL side — the plpgsql packages switch from @libpg-query/parser@17 to libpg-query, whose slim API now includes parsePlPgSQL).

Release strategy (no publish in this PR): publish PG18 packages under the pg18 npm dist-tag, keeping pg17 as latest for now — mirroring the 16→17 rollout. config/versions.json adds the 18 entry (libpg-query 18.1.1, pgsql-parser/pgsql-deparser 18.0.0, npmTag: pg18).

Deparser (pgsql-deparser)

  • returningListreturningClause: new ReturningClause / ReturningOption visitors on INSERT/UPDATE/DELETE/MERGE, incl. RETURNING WITH (OLD AS o, NEW AS n).
  • New ATAlterConstraint node: ALTER TABLE ... ALTER CONSTRAINT c [NOT] ENFORCED | [NOT] DEFERRABLE [INITIALLY DEFERRED] | [NO] INHERIT.
  • Constraint: is_enforced (NOT ENFORCED), generated_kind (GENERATED ... VIRTUAL), without_overlaps / pk_with_period / fk_with_period (temporal PK/FK with WITHOUT OVERLAPS / PERIOD), CONSTR_NOTNULL, CONSTR_ATTR_[NOT_]ENFORCED; removed obsolete AT_CheckNotNull.
  • CreateStmt.nnconstraints, IndexStmt.iswithoutoverlaps, new MergeSupportFunc (merge_action()).
  • PG18 VariableSetStmt.jumble_args used to preserve special SET TIME ZONE ... / SET XML OPTION ... spellings.
  • New location-only fields (rexpr_list_start/end, list_start/list_end, …) added to fixture-cleaning utils.

Transform (@pgsql/transform)

  • New src/18 types/enums, transformers/v17-to-v18.ts, direct transformers v13..v17-to-v18, multi-version registry updated; transformToLatest now targets 18.
  • v17→v18 handles returningListreturningClause, wraps AT_AlterConstraint defs in ATAlterConstraint, and sets jumble_args for VAR_SET_MULTI TRANSACTION forms.
  • Fixed latent transformer bugs surfaced by the new end-to-end (13→18) flow: v16→v17 MergeWhenClause.matchedmatchKind, v13→v14 AlterExtensionContentsStmt objfuncargs handling.
  • Kitchen-sink fixtures regenerated for all version pairs (1437 tests green); irrecoverable cross-version ambiguities (e.g. PG17 AST can't distinguish SET TIME ZONE from SET timezone TO) documented in skip-tests/known-issues.ts.

PL/pgSQL packages (plpgsql-parser / plpgsql-deparser / plpgsql-parse / parse)

Switched to libpg-query@18.1.1. PG18's PL/pgSQL serialization changed in ways the deparser now handles:

  • out_param_varno is no longer serialized when 0 → new resolveOutParamVarno() (finds the (unnamed row) OUT-param datum, falls back to returnInfo), so RETURN; / RETURN NEXT; are still suppressed correctly in OUT-param functions.
  • RETURN NEW now arrives as retvarno instead of expr text → deparse emits RETURN NEW/RETURN OLD (uppercase; source casing is not recoverable).
  • PLpgSQL_rec now carries datatype (source-cased, e.g. record vs RECORD) → declarations preserve it; %rowtype/%type suffix casing normalized.
  • generated.json regenerated: 27 fixtures skipped where PG18 rejects them at parse time (PG18 now validates e.g. RETURN expr in procedures, OUT+VARIADIC, unknown domain-array return types, %type[]); snapshots updated for the casing changes above.

Fixture churn categories

  1. New PG18 fixtures (__fixtures__/kitchen-sink/misc/pg18.sql, transform 17-18 suites).
  2. Regenerated kitchen-sink/transform fixtures from the new proto (field additions only).
  3. PL/pgSQL snapshot updates: record-case preservation and RETURN NEW/new casing.
  4. Skipped PL/pgSQL fixtures that PG18 rejects at parse time (listed above).

Not supported / known limits

  • v17→v18 transformer cannot reconstruct jumble_args for special SET TIME ZONE / SET XML OPTION (info missing from PG17 AST) — documented as known issues.
  • pgsql-types and @pgsql/cli have no test files (jest exits "No tests found") and repo-wide pnpm run lint fails on ESLint 9 vs .eslintrc — both pre-existing on main, untouched here.

Verification

pnpm run build green; all package test suites green: deparser 714, transform 1437, plpgsql-deparser 106, plpgsql-parser 285, plpgsql-parse 57, parse 68, parser 9, quotes 57, traverse 12, utils 4, proto-parser 42.

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

@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

socket-security Bot commented Jul 21, 2026

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@​pgsql/​enums@​18.0.0941009593100
Added@​pgsql/​types@​18.0.010010010093100
Addedlibpg-query@​18.1.110010010095100

View full report

@pyramation
pyramation merged commit 8c387f2 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