Repository navigation
feat(golang): add emit_read_only_prepared to generate read-only queries - #4669
Open
jarri-abidi wants to merge 1 commit into
Open
jarri-abidi wants to merge 1 commit into
jarri-abidi wants to merge 1 commit into
Conversation
Add an emit_read_only_prepared option for database/sql. When set, sqlc also generates read.go with a ReadQueries type, created with PrepareReadOnly, that prepares only the read-only queries: those that SELECT and do not INSERT, UPDATE, DELETE or SELECT ... FOR UPDATE. This lets read queries be prepared on a connection whose database user can only read, such as a read replica, without preparing write statements that user isn't allowed to prepare. Prepare is unchanged and keeps every query, and the models are shared, so nothing is duplicated. read.go gets its imports from the read-only queries' own argument and result types, including lib/pq when they bind or scan slices with pq.Array. Keywords are matched when followed by any whitespace, so queries written as "SELECT\n col1, ..." are recognised. pgx is not supported; no read.go is generated for it. Adds the option to the docs and both config schemas, and endtoend fixtures for MySQL, PostgreSQL, and PostgreSQL with slice arguments and results. Closes sqlc-dev#3187. Supersedes sqlc-dev#3291, which was closed for merge conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jarri-abidi
marked this pull request as ready for review
October 29, 2026 17:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #3187. Supersedes #3291, which was closed automatically for merge conflicts; this is the same feature rebased onto the current
main, with the fixes from running it since.Problem
With
emit_prepared_queries,Prepareprepares every query on one connection. A database user that can only read, such as one connecting to a read replica, can't prepare theINSERT,UPDATEandDELETEstatements, so you either prepare everything with a read-write user or generate a second package and duplicate all the models (#3187).Solution
A new
emit_read_only_preparedoption (Go,database/sql). When set, sqlc also generatesread.gowith aReadQueriestype, created withPrepareReadOnly, that prepares only the read-only queries.Prepareis unchanged, and the models are shared.A query is read-only if it
SELECTs and doesn'tINSERT,UPDATE,DELETEorSELECT ... FOR UPDATE, so aDELETE ... WHERE id IN (SELECT ...)stays out ofread.go, as asked in the #3291 review. Keywords are matched when followed by any whitespace, so queries written asSELECT\n col1, ...are recognised.read.gogets its imports from the read-only queries' own argument and result types, includinggithub.com/lib/pqwhen they bind or scan slices withpq.Array.pgxisn't supported (noread.gois generated), becauseemit_prepared_queriesdoesn't apply to it.Changes
emit_read_only_preparedin the Go options, the v1 config, both config JSON schemas anddocs/reference/config.mdreadQueriesFiletemplate (stdlib/readonlyCode.tmpl) and the read-only query selection ingen.goread_write_segregation: MySQL, PostgreSQL, and PostgreSQL with slice arguments and resultsTesting
go vet ./...andgo test --tags=examples ./...pass locallyread.go, which is where thepqimport and bare-SELECTfixes came from🤖 Generated with Claude Code