Skip to content

feat(pgx-v5): Add static typing support for jsonb_build_object#4518

Open
m-ali-akbay wants to merge 3 commits into
sqlc-dev:mainfrom
m-ali-akbay:pgx-v5-jsonb
Open

feat(pgx-v5): Add static typing support for jsonb_build_object#4518
m-ali-akbay wants to merge 3 commits into
sqlc-dev:mainfrom
m-ali-akbay:pgx-v5-jsonb

Conversation

@m-ali-akbay

@m-ali-akbay m-ali-akbay commented Jul 18, 2026

Copy link
Copy Markdown

Adds a sqlc.jsonb_build_object."Name"(key, value, ...) directive for returning JSON-shaped results that decode straight into a Go struct. It's handy for pulling a one-to-many relationship into a single query instead of running one query per parent row.

-- name: GetAuthors :many
SELECT
  authors.id,
  ARRAY(
    SELECT sqlc.jsonb_build_object."Book"('id', books.id, 'title', books.title)
    FROM books WHERE books.author_id = authors.id
  ) AS books
FROM authors;

gives you:

type GetAuthorsRow struct {
	ID    int64
	Books []Book
}

type Book struct {
	ID    int64  `json:"id"`
	Title string `json:"title"`
}

A few notes:

  • pgx/v5 onlygenerate fails with a clear error for any other sql_package. pgx decodes the jsonb value into the struct (or []struct inside ARRAY(...)) directly, so there's no Scan/Value plumbing.
  • The struct name is required and read off the qualified call — Postgres parses sqlc.jsonb_build_object."Book" as catalog.schema.name, so no new parser work.
  • Nesting works: a value can be another jsonb_build_object or an ARRAY(...) of one.
  • Two queries that use the same name share one Go type when their shapes match; a shape mismatch or a collision with a model fails generation. Names and fields can be overridden with rename.
  • Internally the call is just rewritten to Postgres's jsonb_build_object before analysis.

Docs in docs/howto/embedding.md; covered by unit tests plus a sqlc_json golden fixture.

Add two directives that return JSON-encoded results decoded directly into
Go structs by pgx/v5, including nested objects and arrays from a single query:

  - sqlc.jsonb_build_object."Name"(key, value, ...) builds an arbitrary
    named struct from key/value pairs.
  - sqlc.embed.jsonb(table) builds a struct mirroring a whole row, as a
    shorthand that composes inside ARRAY(...) for slices of rows.

Both are rewritten to real Postgres functions (jsonb_build_object / to_jsonb)
before analysis; pgx/v5 decodes the jsonb value into a plain struct (or slice)
with no Scan/Value plumbing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@m-ali-akbay
m-ali-akbay marked this pull request as ready for review July 18, 2026 08:21
The process_plugin_sqlc_gen_json fixture serializes the full CodeGenRequest,
so adding json_fields/json_name to Column changes its output. Only
codegen_json had been regenerated; this test skips locally when the
sqlc-gen-json binary isn't on PATH, so CI caught it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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