Repository navigation
storage: apply staged Postgres sink updates to the target table - #39707
patrickwwbutler wants to merge 1 commit into
Conversation
QA LLM Review1. MEDIUM -- Keyless sinks with a column named
|
| continue; | ||
| }; | ||
| // Ignore progress below where we resumed. | ||
| if !PartialOrder::less_equal(&resume_upper, &progress) { |
There was a problem hiding this comment.
| if !PartialOrder::less_equal(&resume_upper, &progress) { | |
| if !PartialOrder::less_equal(&lower, &progress) { |
resume upper is not the right thing to check here, and may not even exist
| }), | ||
| " AND ", | ||
| ); | ||
| sql!( |
There was a problem hiding this comment.
verify that this works with updates containing multiple ticks - potentially many updates to a single key and we need to make sure we only emit the correct retraction, and only insert the single correct value
8baa201 to
a9ccbd1
Compare
Complete the write loop. Each completed timestamp window is applied to the target table in the transaction that staged it, and the new frontier is recorded in materialize.sink_progress only while the row still carries this incarnation's epoch. The persist progress shard is brought up to that frontier after the commit, and reconciled forward at startup. A keyed sink takes every key a window touches straight from its state before the window to its state after it, with at most one INSERT, UPDATE or DELETE per key, so a window holding several timestamps for one key never puts the key in the target table twice. A keyless sink inserts and retracts exact row multiplicities. Adds unit tests, run against the database at POSTGRES_URL, for key replacement, one operation per key, rejected windows, keyless multiplicities and fencing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
a9ccbd1 to
078bfa9
Compare
QA LLM Review1. HIGH -- Applying unclosed timestamps breaks exactly-once replay
The new commit path applies every staged row, including timestamps at or beyond the progress frontier. Those rows are committed with an earlier resume frontier, so a restart replays them, silently duplicating keyless output or blocking keyed sinks on duplicate-key errors. Details
For example, staging an insertion at time 10 and committing frontier 5 inserts the row immediately. Restarting from 5 then applies the insertion again. The generated SQL on PostgreSQL 17 produces two copies for a keyless target and a primary-key violation for a keyed target. Apply only timestamps strictly below 2. MEDIUM -- Keyless retractions fail on partitioned targets with overlapping ctids
The keyless delete identifies rows only by DetailsExisting partitioned targets pass the Carry |
Complete the write loop. Each completed timestamp window is applied to
the target table in the transaction that staged it, and the new frontier
is recorded in materialize.sink_progress only while the row still
carries this incarnation's epoch. The persist progress shard is brought
up to that frontier after the commit, and reconciled forward at startup.
A keyed sink takes every key a window touches straight from its state
before the window to its state after it, with at most one INSERT, UPDATE
or DELETE per key, so a window holding several timestamps for one key
never puts the key in the target table twice. A keyless sink inserts and
retracts exact row multiplicities.
Tests: adds unit tests in
src/storage/src/sink/postgres.rs, run against the database atPOSTGRES_URL, for key replacement, one operation per key, rejected windows, keyless multiplicities and fencing. Also covered end to end bytest/pg-sinkat the top of this stack.🤖 Generated with Claude Code