feat(findings): replica_identity_missing — a published table that can't be updated - #113
Merged
alexshapalov merged 1 commit intoSep 30, 2026
Merged
Conversation
Contributor
Author
|
I ran this against a
The dropped-index case is the one I wouldn't have guessed: after |
Contributor
|
@lofoneh, tnx, pls resolve conflicts |
…'t be updated A table published for UPDATE or DELETE needs a replica identity so the subscriber can find the row. Without one Postgres rejects the write itself: "cannot update table … because it does not have a replica identity and publishes updates". Reads and INSERTs keep working, so the failure lands on the first UPDATE after a migration, not at deploy time. A catalog-only gauge collector reads pg_publication and pg_class: DEFAULT with no primary key, NOTHING, or USING INDEX whose index is gone or invalid. Insert-only publications need no identity and are not reported. Scope is schema, so it runs under --profile=schema and pgbot lint on an empty CI database — the migration-PR path where this is worth catching. The integration fixture proves the UPDATE fails before asserting the finding, then that a primary key clears both. New replica_identity section in --json; SchemaVersion 1.5.0 (additive) — pgrundev#38 took 1.4.0 first, so this is the next minor.
lofoneh
force-pushed
the
feat/replica-identity-finding
branch
from
September 30, 2026 02:49
f41442c to
a0c07f0
Compare
Contributor
Author
|
@alexshapalov , Conflicts resolved. #38 took 1.4.0, so this is 1.5.0 now and the schema's regenerated. |
elkaix
added a commit
to elkaix/pgbot
that referenced
this pull request
Oct 1, 2026
pgrundev#113 landed after pgrundev#114 removed pgx from go.mod, so the test's pgx import left the collect package unbuildable under go vet / go test ./...
Open
4 tasks done
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.
What
A table published for
UPDATEorDELETEneeds a replica identity so the subscribercan find the row. Without one, Postgres refuses the write:
Reads and INSERTs keep working, so you don't find out at deploy time — you find out
on the first UPDATE after the migration. This adds a finding for it.
It reads the catalog only —
pg_publication,pg_publication_tables,pg_class,pg_namespace,pg_index— so it'sschemascope andpgbot lintcatches it on an empty CI database. Insert-only publications need no identity and are
skipped. I deliberately didn't flag every table without a primary key — that fires on
append-only tables and partitions where it's intended.
Note: #46 also bumps the schema to 1.4.0. Whichever lands second needs a renumber, and
I'm happy to rebase.
Verification
On PG 18.6:
then asserts the finding. Adding a primary key clears both.
pgbot lintexits 2 with the finding, and cleanly once there's a key.scripts/gate.shgreen.Checklist
scripts/gate.shpasses (builds HEAD, not just the working tree)EXPLAIN ANALYZE; findings stay deterministic (computed in Go)model.Context/--json/ the store — relation and publication names only--jsonchange is additive,model.SchemaVersionbumped + schema regenerateddocs/findings/<id>.mdpage + catalog entry