Skip to content

fix(postgres): read and write arrays with their element's delimiter - #84

Merged
colinhacks merged 3 commits into
mainfrom
fix-array-delimiter
Oct 23, 2026
Merged

colinhacks merged 3 commits into
mainfrom
fix-array-delimiter

Conversation

@colinhacks

Copy link
Copy Markdown
Owner

PostGIS's geometry and geography separate the elements of an array with :, not , (their typdelim), and so does built-in box with ;. Reylo assumed a comma wherever a module told it a column's kind:

  • Results. select array['POINT(1 2)'::geometry, 'POINT(3 4)'] came back from .run() as one merged string, ['0101…:0101…'], on the module path of every Postgres driver (the decoder learned the created type from the module's column kind with a , delimiter, and kept that for the client, so a hand-defined query on the same client inherited it). Bun.sql's string arrays went through coerce's comma too.
  • Parameters. where g = any(:gs) with two or more geometries failed with malformed array literal, since arrayLiteral always joined with ,.

The fix carries the delimiter from the catalog:

  • The engine's type query reads typdelim; an array type (Type::Array, EngineType's array) carries delimiter where its element's is not a comma. A domain has its base type's.
  • A module's columns carry it as a third element, ["shapes", "text[]", ":"], which the pg-family, PGlite, postgres.js and Bun.sql decoders use.
  • arrayLiteral writes an array parameter with the delimiter its input type carries, between sub-arrays too.

Tests: the decode fakes gain a created array type with :, on every Postgres driver's path (8 tests fail without the fix), arrayLiteral with : and ;, a parameter bound through a module's inputs, and an engine unit test for the delimiter of a type's array and of a domain's. Checked live on Supabase's and Neon's Postgres 17 images with PostGIS; the driver matrix (4154 rows over 57 jobs, 0 different), the oracle, the loader's tests and the rebuilt engine.wasm pass.

Copilot AI balanced review requested due to automatic review settings October 23, 2026 20:36
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Oct 23, 2026 8:48pm UTC

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ℹ️ No critical issues — one small redundant argument inline.

Reviewed changes

I reviewed the whole diff: the engine now records the element delimiter from the catalog, the module carries it, and the run time uses it.

  • typdelim in the type registry: TYPE_QUERY and RELATION_TYPES_QUERY now read t.typdelim. insert_rows keeps it only when it is not a comma, and render puts the element's delimiter on Type::Array. A domain picks up its base type's delimiter, because the catalog copies it onto the domain's row. Both box (not in BUILTINS, so it is looked up) and PostGIS's geometry get theirs.
  • with_items preserves it: every other Type::Array site is mechanical (delimiter: None). All three engine.wasm files are rebuilt, as a change under core requires, and the fingerprint in the .reylo/ cache key throws away entries cached without the delimiter.
  • Module columns [name, kind, delimiter?]: arrayDelimiter in src/values.ts produces them. Inputs already carry the full EngineType, so delimiter reaches arrayLiteral for parameters, nested arrays included.
  • Decoders: fieldDecoders seeds the client's learned types with the column's delimiter, so later hand-defined queries on the same client decode correctly too. Bun.sql passes the delimiter through bunValue to coerce. The catalog path (learn) already read typdelim before this PR.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread src/decode.ts Resolved
PostGIS's geometry and geography separate array elements with ':'
(box with ';'), so a geometry[] column came back as one merged string
and a geometry[] parameter failed as a malformed array literal. The
engine reads typdelim with each type, an array type carries it, and the
module's columns and inputs hand it to the decoders and arrayLiteral.
@colinhacks
colinhacks merged commit b4d444c into main Oct 23, 2026
6 checks passed
@colinhacks
colinhacks deleted the fix-array-delimiter branch October 23, 2026 21:03
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.

2 participants