Conversation
`ConfigAndUsers::prepared_statements()` only looked at the `[general]` pooler mode. With `[general] pooler_mode = "session"` and a user or database overridden to `"transaction"`, prepared statement tracking was disabled for that user even though its pool multiplexes server connections. Under read/write split a named Parse (routed to a replica) and its Bind (routed to the primary when untracked) landed on different servers, so drivers with statement caches (pgx, npgsql, etc.) failed with `prepared statement "..." does not exist` (SQLSTATE 26000). Add `ConfigAndUsers::prepared_statements_for(pooler_mode)` and have the client and mirror derive the level from the pooler mode of the cluster they are actually bound to, while still reading the level itself from live config on every request as before. Admin clients have no cluster and keep the `[general]` behaviour. Fixes pgdogdev#1536
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…ients
`prepared_statements_for(Session)` forced tracking off per cluster,
which broke `test_session_multiple_statements_in_transaction`: a
session-pooled user on a schema-sharded cluster sends a named Parse +
Bind once psycopg auto-prepares, and without a tracked statement the
router has no SQL to route the Bind, so it lands on the wrong shard
("cannot switch shards in a direct-to-shard transaction").
Only multiplexing pools (transaction and statement mode) override the
`[general]` default; session-pooled clients keep the existing
`[general]`-derived behaviour, so nothing changes for them relative to
main.
levkk
reviewed
Sep 15, 2026
| /// Prepared statements level for clients using the `[general]` pooler mode. | ||
| /// | ||
| /// Prefer [`Self::prepared_statements_for`] with the pooler mode the client's | ||
| /// pool actually runs in: users and databases can override `pooler_mode`. |
Collaborator
There was a problem hiding this comment.
Shouldn't this function re-use prepared_statements_for? Seems cleaner / less duplication.
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.
ConfigAndUsers::prepared_statements()only looked at the[general]pooler mode. With[general] pooler_mode = "session"and a user or database overridden to"transaction", prepared statement tracking was disabled for that user even though its pool multiplexes server connections. Under read/write split a named Parse (routed to a replica) and its Bind (routed to the primary when untracked) landed on different servers, so drivers with statement caches (pgx, npgsql, etc.) failed withprepared statement "..." does not exist(SQLSTATE 26000).Add
ConfigAndUsers::prepared_statements_for(pooler_mode)and have the client and mirror derive the level from the pooler mode of the cluster they are actually bound to, while still reading the level itself from live config on every request as before. Admin clients have no cluster and keep the[general]behaviour.Fixes #1536