Skip to content

datastore/postgres: honour PreferSimpleProtocol/PreparedStatements at the pgx layer - #698

Merged
pitabwire merged 1 commit into
mainfrom
fix/pgx-query-exec-mode
Sep 4, 2026
Merged

datastore/postgres: honour PreferSimpleProtocol/PreparedStatements at the pgx layer#698
pitabwire merged 1 commit into
mainfrom
fix/pgx-query-exec-mode

Conversation

@pitabwire

Copy link
Copy Markdown
Owner

Problem

Adapter.OpenConnection passes an open *sql.DB to gormpostgres.New, and gorm-postgres only applies PreferSimpleProtocol when it parses the DSN itself. So pool.WithPreferSimpleProtocol(true) (and the pool default of true) never reached pgx, which stayed in QueryExecModeCacheStatement. Behind a transaction-mode pooler (PgBouncer, Supavisor, Neon pooler) that fails with prepared statement "stmtcache_…" does not exist / already exists (SQLSTATE 26000/42P05) once connections are reassigned. service-trustage hit this in production on 2026-09-01 (Supabase pooler :6543) and is running on a default_query_exec_mode=simple_protocol DSN workaround.

Change

applyQueryExecMode sets ConnConfig.DefaultQueryExecMode from the connection options before the pool is created:

options mode
PreferSimpleProtocol simple_protocol
!PreparedStatements exec (extended protocol, no server-side prepared statements)
otherwise cache_statement (pgx default, unchanged)

An explicit default_query_exec_mode in the DSN still wins. postgres.QueryExecMode is exported for inspection.

Behaviour note

pool.NewPool defaults PreferSimpleProtocol to true, so services that never overrode it now actually use the simple protocol as documented. Services that want the statement cache should set pool.WithPreferSimpleProtocol(false).

Tests: unit tests for mode selection and DSN override; go test ./datastore/... green locally.

https://claude.ai/code/session_016Bc2hUCUhZkA51qkHQ8UWX

… at the pgx layer

gorm's postgres driver only honours Config.PreferSimpleProtocol when it
parses the DSN itself. The adapter hands it an already-open *sql.DB, so the
preference every service sets (and the pool default of true) was silently
dropped and pgx stayed in its statement-cache mode. Behind a
transaction-mode pooler (PgBouncer, Supavisor, Neon) that fails with
"prepared statement ... does not exist / already exists" (SQLSTATE
26000 / 42P05) as soon as pooled connections are reassigned; service-trustage
hit this in production on 2026-09-01 and needed a DSN workaround.

Set ConnConfig.DefaultQueryExecMode from the connection options:
simple_protocol when PreferSimpleProtocol, exec when prepared statements are
disabled, cache_statement otherwise. An explicit default_query_exec_mode in
the DSN still wins. QueryExecMode is exported so callers can inspect it.

Claude-Session: https://claude.ai/code/session_016Bc2hUCUhZkA51qkHQ8UWX
@pitabwire
pitabwire merged commit 244aa85 into main Sep 4, 2026
5 checks passed
@pitabwire
pitabwire deleted the fix/pgx-query-exec-mode branch September 4, 2026 12:43
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