Add agtype <-> jsonb bidirectional casts (#350)#2361
Conversation
There was a problem hiding this comment.
Pull request overview
Adds explicit, bidirectional casts between agtype and jsonb so users can interoperate with PostgreSQL’s jsonb operators/functions and pass jsonb into Cypher contexts without manual conversion steps.
Changes:
- Add
ag_catalog.agtype_to_jsonb(agtype)SQL wrapper andCREATE CAST (agtype AS jsonb). - Add
ag_catalog.jsonb_to_agtype(jsonb)SQL wrapper andCREATE CAST (jsonb AS agtype). - Document rationale for using a textual/JSON intermediate to avoid binary-format incompatibilities.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@gregfelice Please see the above comments by Copilot |
|
Addressed both Copilot suggestions:
All regression tests pass ( |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
c1ce37e to
6801d3a
Compare
|
Rebased onto The PR now contains only the 2 cast-specific commits:
The 3 Copilot comments about pattern expression code (cypher_gram.y comment placement, %expect/%expect-rr, Makefile scope) are no longer applicable. The 2 original Copilot suggestions (comment/implementation mismatch, regression test coverage) were already addressed in the previous round. Regression test: agtype_jsonb_cast OK. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@gregfelice It looks like just one item left and we're good. |
|
@jrgemignani — resolved the final Copilot thread. The PR description already reflects the regression test and Makefile changes (see "Files changed"). All items addressed; ready for merge when you have a moment. Thanks! |
|
Gentle bump — all Copilot feedback has been resolved (since 2026-04-15), CI is green on the 6 checks, and the branch still merges cleanly against current |
|
@gregfelice Sorry for the delay. Can you rebase this with the master, plz. It is complaining that there are conflicts. |
|
On it |
Register explicit casts between agtype and jsonb, enabling:
SELECT properties(n)::jsonb FROM cypher(...) AS (n agtype);
SELECT '{"key": "value"}'::jsonb::agtype;
-- Use jsonb operators on graph data:
SELECT (props::jsonb)->>'name' FROM cypher(...) AS (props agtype);
Implementation uses SQL language functions that go through proven
text-intermediate paths:
agtype -> jsonb: agtype_to_json() -> json::jsonb
jsonb -> agtype: jsonb::text -> text::agtype
This approach is safe because agtype extends jsonb's binary format
with types (AGTV_INTEGER, AGTV_FLOAT, AGTV_VERTEX, AGTV_EDGE,
AGTV_PATH) that jsonb does not recognize, making direct binary
conversion unreliable. The text roundtrip handles all value types
correctly including graph types (vertex/edge properties are
extracted as JSON objects).
All 31 regression tests pass.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…asts - Fix comment in agtype_coercions.sql: document json-intermediate path (agtype_to_json -> json::jsonb) instead of incorrect "text intermediate" - Add agtype_jsonb_cast regression test covering: string/null/array/object agtype->jsonb, all jsonb scalar types->agtype, roundtrips, vertex/edge ->jsonb with structural key checks, NULL handling - Register agtype_jsonb_cast in Makefile REGRESS list Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The age_upgrade regression test (added after this PR was originally opened) verifies that every SQL object in the install SQL also appears in the version upgrade template (age--<INIT>--<CURR>.sql). Surfaced during rebase onto current master: agtype_to_jsonb / jsonb_to_agtype and their casts were missing from the template, causing 4 entries in the "missing_function" / "missing_cast" check. Adds the two functions and two casts to the end of the template, following the file's own "add all additions to the end of this file" convention. Cassert installcheck now 34/34 AGE tests green (pgvector skipped — env-only).
|
@jrgemignani — rebased onto current Conflict resolution: only one conflict, in Post-rebase discovery — third commit added ( Cassert installcheck: 35/36 AGE tests green (pgvector skipped — |
6801d3a to
506138f
Compare
Summary
Adds explicit casts between
agtypeandjsonb(issue #350, open since 2022):Implementation
SQL language functions using json-intermediate paths:
agtype → jsonb:ag_catalog.agtype_to_json($1)::jsonbjsonb → agtype:$1::text::agtypeWhy json intermediate? agtype extends jsonb's binary format with types (
AGTV_INTEGER,AGTV_FLOAT,AGTV_VERTEX,AGTV_EDGE,AGTV_PATH) that jsonb does not recognize. Direct binary cast causes"unknown type of jsonb container"errors. The json roundtrip correctly handles all value types — graph types are serialized as JSON objects with their properties.Files changed
sql/agtype_coercions.sql— adds the two cast functions andCREATE CASTstatements (27 lines).regress/sql/agtype_jsonb_cast.sql+regress/expected/agtype_jsonb_cast.out— new regression suite covering scalar/array/object roundtrips, all jsonb scalar types → agtype, vertex/edge → jsonb with structural key checks, and NULL handling (137 + 261 lines).Makefile— registersagtype_jsonb_castin theREGRESSlist so the new suite runs as part ofmake installcheck.No C code changes.
Test plan
'{"name": "Alice", "age": 30}'::agtype::jsonb'[1, 2, 3]'::agtype::jsonb'"hello"'::agtype::jsonb'{"a": {"b": [1, true, null]}}'::agtype::jsonb'{"key": "value"}'::jsonb::agtype('{"x": 1}'::agtype::jsonb)::agtype(props::jsonb)->>'name'agtype_jsonb_castregression suite passes🤖 Generated with Claude Code