GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add a :type annotation to share a row type between queries by egimbernat · Pull Request #4630 · sqlc-dev/sqlc

Conversation

@egimbernat

@egimbernat egimbernat commented Oct 2, 2026

Copy link
Copy Markdown

Queries that select the same columns each get their own row struct (GetBookRow, ListBooksByAuthorRow, …) even when the structs are identical, so callers end up converting between them. This adds an optional :type <TypeName> after the command:

-- name: GetBook :one :type BookWithAuthor
SELECT books.id, books.title, authors.name AS author_name
FROM books JOIN authors ON authors.id = books.author_id
WHERE books.id = $1;

-- name: ListBooksByAuthor :many :type BookWithAuthor
SELECT books.id, books.title, authors.name AS author_name
FROM books JOIN authors ON authors.id = books.author_id
WHERE books.author_id = $1;

Both methods return BookWithAuthor, which is emitted once. It works with sqlc.embed as well.

Compatibility is checked strictly, as #3595 asks: generation fails when two queries naming the same type would give different fields (name, Go type or struct tag, in order), and the error names the first differing column:

query ListBooks: :type BookWithAuthor does not match query GetBook: column 3 is AuthorID int64, want AuthorName string

It also fails if the name is already a model's or the query returns a single column, since there is no struct to name. An explicit :type wins over the existing reuse of a table's model when the columns happen to match one.

Changes

  • metadata.ParseQueryNameAndType now returns Metadata (with the new TypeName) instead of two strings, so its three callers no longer rebuild it from parts.
  • plugin.Query gets type_name = 9 (regenerated with buf generate), so plugins for other languages can honour the annotation. The two JSON plugin goldens gain the field.
  • Go codegen: rowTypes in internal/codegen/golang/result.go.
  • Docs: new howto/row_types.md, plus a note in reference/query-annotations.md.
  • Tests: endtoend case query_type_annotation (plain columns, aliases, sqlc.embed, and a query whose columns match a model), and four failing cases with stderr.txt: mismatched columns, a model's name, a single column, and malformed annotations.

go test --tags=examples ./... passes locally against PostgreSQL 16 and MySQL 9.

Fixes #781
Fixes #3595
Related: #2252, which asks to return an existing model; this names a shared type instead.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

sgielen reacted with heart emoji
All reactions
  • ❤️ 1 reaction
@egimbernat ali
Add a :type annotation to share a row type between queries
e467f17
A query that returns more than one column gets a struct named after it, so
queries selecting the same columns return different types. `:type <TypeName>`
after the command names the row type instead, and queries that use the same
name return one struct. Generation fails if their columns give different
fields, if the name is a model's, or if the query returns a single column.

Plugins receive the name as Query.type_name. ParseQueryNameAndType now
returns the Metadata, so its callers no longer rebuild it from parts.

Fixes sqlc-dev#781
Fixes sqlc-dev#3595

Co-authored-by: ali <[email protected]>
@sgielen

sgielen commented Oct 16, 2026

Copy link
Copy Markdown

Oh this would be great to have. In my larger production codebases, I often have multiple queries returning the same columns, and it's always annoying to cast one result type to other result types, especially for :many queries where this means I have to loop over the whole result array just to cast it. Really hoping this can be merged!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Allow the specification of shared row datatypes Override query return type

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@egimbernat @sgielen
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.