Skip to content

Convert composite values structurally, in both directions#25

Merged
jdatcmd merged 1 commit into
masterfrom
record-parser
Jul 6, 2026
Merged

Convert composite values structurally, in both directions#25
jdatcmd merged 1 commit into
masterfrom
record-parser

Conversation

@jdatcmd

@jdatcmd jdatcmd commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Completes the structural-conversion story begun with array columns in 2.3.0. Full suite green on PG 11–18 + jsonb_plphp in the container sweep; CI (including the new ASAN job) validates on this PR.

Forward

Composite-typed columns in rows, fields of composite arguments, and composites inside arrays now arrive as associative PHP arrays — recursively:

$row = spi_fetch_row($r);
$row['who']['home']['city']    // nested composite field, a real string
$row['who']['tags'][1]         // array field inside the composite

Reverse (symmetric)

A PHP array destined for a composite slot — return value, return_next column, OUT argument, or trigger MODIFY field — renders as a record literal:

$_TD['new']['who']['home']['city'] = 'Changed';   // nested MODIFY works
return 'MODIFY';

Implementation: a parser for the composite output format (quote/backslash doubling, empty-field NULLs, dropped columns) mirrored by an always-quoting record-literal builder; the array parser/builder gained an element-type parameter so composite elements convert too. Escaping torture cases (embedded quotes, commas, parens, backslashes) are pinned in the tests both directions.

Rider

anycompatible/anycompatiblearray accepted as polymorphics on PG 13+ (an arrays_1.out variant covers 11/12 where the types don't exist).

🤖 Generated with Claude Code

Completes the structural-conversion work begun with array columns:
composite-typed columns in rows, the fields of composite arguments,
and composites inside arrays now arrive in PHP as associative arrays,
recursively (a composite containing arrays containing composites
nests all the way down).  The reverse direction works symmetrically:
a PHP array destined for a composite-typed slot -- a return value, a
return_next row's column, an OUT argument, or a trigger MODIFY field
-- is rendered as a record literal, so nested structures can be built
from plain PHP arrays and modified in place in triggers.

The machinery is a parser for the composite output format (quote and
backslash doubling, empty-field NULLs, dropped-column skipping),
mirrored by a record-literal builder that always double-quotes
non-null fields; the array parser and builder gained an element-type
parameter so composite elements convert too.  Column/field semantics
match row columns (scalars stay strings); the per-argument element
type replaces the old arg_is_array flag.

Also accept anycompatible and anycompatiblearray as polymorphic
argument/return types on PostgreSQL 13+ (an arrays_1.out variant
covers 11/12, where the types do not exist).

New regression cases: composite columns with nested composite and
array fields (with embedded quotes, commas, and parentheses),
composite arguments, composites inside array arguments, building a
nested composite from associative arrays, trigger MODIFY through a
nested composite field, NULL fields in both directions, and the
anycompatible polymorphics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jdatcmd jdatcmd merged commit 9f3c9be into master Jul 6, 2026
12 checks passed
@jdatcmd jdatcmd deleted the record-parser branch July 6, 2026 05:00
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