From d67bb43755896909663daa62fb0ae19b32b9d75e Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Fri, 17 Apr 2026 11:12:36 +0800 Subject: [PATCH v1] Reject deferrable primary key fallback in REPACK CONCURRENTLY REPACK CONCURRENTLY uses logical decoding to collect concurrent changes and then replays them on the new heap. To locate rows for UPDATE and DELETE replay, it requires an identity index. When RelationGetReplicaIndex() returned InvalidOid, the code fell back to rel->rd_pkindex if a primary key existed. That is not safe for deferrable primary keys. Such indexes are not considered replica identity indexes by WAL generation, so logical decoding may not provide the old tuple needed by the repack output plugin. This can make replay fail later with errors such as "incomplete delete info" from the decoding worker. Prevent the fallback when the primary key is deferrable, and report the problem during the initial REPACK CONCURRENTLY checks instead. Author: Chao Li Reviewed-by: Discussion: https://postgr.es/m/ --- src/backend/commands/repack.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 67364cc60e3..2c89cd17db4 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -926,7 +926,21 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) */ ident_idx = RelationGetReplicaIndex(rel); if (!OidIsValid(ident_idx) && OidIsValid(rel->rd_pkindex)) + { + /* + * A deferrable primary key is not considered a replica identity + * index, so WAL may not contain the old tuple needed for replay. + */ + if (rel->rd_ispkdeferrable) + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot process relation \"%s\"", + RelationGetRelationName(rel)), + errhint("Relation \"%s\" has a deferrable primary key.", + RelationGetRelationName(rel))); + ident_idx = rel->rd_pkindex; + } if (!OidIsValid(ident_idx)) ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), -- 2.50.1 (Apple Git-155)