Skip to content

fix: route extended-protocol copy-in termination through Sync - #465

Merged
sunng87 merged 3 commits into
masterfrom
fix/extended-copy-in-sync
Sep 21, 2026
Merged

sunng87 merged 3 commits into
masterfrom
fix/extended-copy-in-sync

Conversation

@sunng87

@sunng87 sunng87 commented Sep 21, 2026

Copy link
Copy Markdown
Owner

We will only await for Sync after CopyDone is sent from client. Will reject any other messages during the copy.

After a successful extended-protocol COPY FROM STDIN, the connection
stayed in `CopyInProgress(true)` state and the client's terminating
Sync message was swallowed by the catch-all arm of the state matcher.
`on_sync` therefore never ran, `ReadyForQuery` was never sent, and the
connection deadlocked: clients built on rust-postgres/tokio-postgres
complete the copy with CopyDone followed by Sync, so every extended
copy-in froze the connection after its first batch.

Two changes, both mirroring PostgreSQL:

- after a successful `on_copy_done` in extended mode, transition the
  connection to `AwaitingSync` so the client's trailing Sync is
  dispatched to `on_sync`, which sends `ReadyForQuery` and returns the
  connection to normal operation (this is what the existing comment
  intended, but the state machine never made the Sync reachable);
- a Sync received while the copy is still unfinished (no preceding
  CopyDone/CopyFail) is rejected with an 08P01 protocol violation,
  like PostgreSQL rejects any unexpected message type during COPY,
  instead of being silently discarded.

Adds regression tests driving both query protocols over raw TCP: the
extended round trip (Sync after CopyDone completes with ReadyForQuery
and the connection serves further queries), the mid-copy Sync
rejection with connection recovery, and the simple protocol round
trip. Without the fix the extended tests fail by timeout, reproducing
the deadlock.

Signed-off-by: Ning Sun <sunning@greptime.com>
@sunng87
sunng87 merged commit 6048a2d into master Sep 21, 2026
11 checks passed
@sunng87
sunng87 deleted the fix/extended-copy-in-sync branch September 21, 2026 23:27
redox added a commit to altertable-ai/pgwire that referenced this pull request Sep 28, 2026
rust-postgres pipelines a Sync right after the Execute that starts a
COPY FROM STDIN, before any CopyData. Since sunng87#465 that Sync aborted the
copy with 08P01, breaking every extended-protocol copy from that client.
PostgreSQL ignores Flush and Sync in copy-in mode for exactly this reason.

Co-authored-by: Cursor <cursoragent@cursor.com>
sunng87 pushed a commit that referenced this pull request Sep 29, 2026
* fix: report the tracked transaction status after simple-protocol COPY FROM STDIN

A successful simple-protocol CopyDone always answered ReadyForQuery(Idle),
so a COPY run inside BEGIN made clients that track the transaction state
from ReadyForQuery believe the transaction had ended.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: ignore Flush and Sync during copy-in, like PostgreSQL

rust-postgres pipelines a Sync right after the Execute that starts a
COPY FROM STDIN, before any CopyData. Since #465 that Sync aborted the
copy with 08P01, breaking every extended-protocol copy from that client.
PostgreSQL ignores Flush and Sync in copy-in mode for exactly this reason.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
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