Skip to content

fix(pg): keep a named statement usable after its values fail to serialize - #3797

Open
maxymlyskov wants to merge 1 commit into
brianc:masterfrom
maxymlyskov:fix/named-statement-after-bind-error
Open

maxymlyskov wants to merge 1 commit into
brianc:masterfrom
maxymlyskov:fix/named-statement-after-bind-error

Conversation

@maxymlyskov

Copy link
Copy Markdown

When a value's toPostgres() throws in a named client.query(), every later run of that name fails with prepared statement "<name>" does not exist. The catch around bind() sends Close, so the server drops the statement, but the name stays in parsedStatements and hasBeenParsed skips Parse. On first use the late ParseComplete puts it there.

The catch now closes only the unnamed statement, so a named one stays prepared.

The added tests cover a first use, an already prepared name and a same-name query pipelined behind the failing one. They fail on master and pass here.

The same three cases (A, B, C) from a script against Postgres 16:

# master
PROBE A retry 0 error 26000 prepared statement "a" does not exist
PROBE B retry error 26000 prepared statement "b" does not exist
PROBE C pipelined same-name query behind it: error 26000 prepared statement "c" does not exist
# this branch
PROBE A retry 0 ok [{"v":"ok"}]
PROBE B retry ok [{"v":"two"}]
PROBE C pipelined same-name query behind it: ok [{"v":"behind"}]

…lize

When a value's toPostgres() throws, or JSON.stringify meets a circular
object, the catch around bind() sends a Close for the statement and a
Sync. For a named statement the Close removes it from the server, but
the client still lists it in parsedStatements: on first use the
ParseComplete for the Parse already sent arrives after the catch and
records the name, and on a later use the entry is already there. Every
later query with that name skips Parse and fails with 26000 prepared
statement "<name>" does not exist for the life of the connection, and
so does a query with the same name pipelined behind the failing one.

Only close the unnamed statement. A named statement that parsed stays
prepared and matches the client's cache, so the next run binds to it as
it would after any other error.
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