feat(sink): fail fast on incompatible postgres target tables - #26678
Draft
yuhao-su wants to merge 1 commit into
Draft
feat(sink): fail fast on incompatible postgres target tables#26678yuhao-su wants to merge 1 commit into
yuhao-su wants to merge 1 commit into
Conversation
Statements are prepared lazily since the multi-row batching change, so an incompatible target table (constraint dropped after CREATE SINK, missing DML privilege, read-only endpoint) only surfaced at the first flush, with data already flowing. The writer constructor now: - rejects read-only targets (hot standby / transaction_read_only=on), which EXPLAIN alone cannot catch; - EXPLAINs a single-row write and, for upsert sinks, a single-row delete: planning resolves the ON CONFLICT arbiter and runs executor-start privilege checks, both invisible to prepare; - pre-warms the size-1 statements, a genuine tail size of the batch path. Known limit documented on the probe: executor-init-only checks (e.g. DEFERRABLE arbiters) still surface at the first flush. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5 tasks
Contributor
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
5 tasks
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.

I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.
What's changed and what's your intention?
Stacked on #26677 (which is stacked on #26671).
Statements are prepared lazily since #26671, so an incompatible target table — a unique constraint dropped after
CREATE SINK, a role missing a DML privilege, a read-only endpoint — only surfaced at the first flush, with data already flowing through the sink. The postgres writer constructor now fails fast:pg_is_in_recovery()/transaction_read_only = on, e.g. an RDS/Aurora reader endpoint). This needs its own check becauseEXPLAINis exempt from PostgreSQL's read-only enforcement.EXPLAINwith NULL binds. Planning resolves theON CONFLICTarbiter index and runs executor-start privilege checks; both are invisible toprepare, which performs parse analysis only (verified at the protocol level:PREPAREof a delete succeeds without the DELETE privilege,EXPLAINof it fails;PREPAREof an upsert succeeds on a table without a matching unique index,EXPLAINfails with SQLSTATE 42P10). Nothing is executed:EXPLAINwithoutANALYZEwrites no rows.The probe's bind arity now comes from a shared
params_per_tuple(kind)(also used byprepare_batches), with a unit test pinning it to the$nplaceholder count of each statement kind.Documented limit: executor-init-only checks (e.g. a
DEFERRABLEarbiter) are not exercised byEXPLAINand still surface at the first flush.Verification
EXPLAINwith NULL binds plans and executes nothing; arbiter shown in the plan; privilege and read-only behaviors as described above).e2e_test/sink/postgres_sink.slt(append-only + upsert + batching sections) passes on a local cluster with the probes active at every writer startup.default_transaction_read_only = onfails writer construction with the new error and retries with backoff; afterALTER DATABASE ... SET default_transaction_read_only = off, the sink recovers on its own and drains the backlog (row verified present in the target table).RECOVERmakes writer construction fail withfailed to plan the upsert statement against the target table: ... there is no unique or exclusion constraint matching the ON CONFLICT specificationbefore any row is written; restoring the pk and recovering resumes the sink and drains the backlog.Known follow-ups (separate PRs)
EXPLAINprobe invalidate()as well, so mismatches knowable at DDL time failCREATE SINKinstead of sink startup.condeferrablecheck invalidate()to close theDEFERRABLE-arbiter gap at DDL time.Checklist
Documentation
🤖 Generated with Claude Code