From d46287b2badfb7784b1d609a512fa10cbdee2752 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Tue, 8 Sep 2026 17:17:24 +0000 Subject: [PATCH v5] Restrict REPACK (CONCURRENTLY) to the heap access method. REPACK (CONCURRENTLY) didn't check the table AM of the table being repacked, so if the table AM doesn't support logical decoding, the concurrent changes are never decoded and are silently lost from the rewritten table. Fix by erroring out for tables that use a non-heap access method. Reported-by: Nathan Bossart Author: Bharath Rupireddy Reviewed-by: Nathan Bossart Reviewed-by: Masahiko Sawada Discussion: https://postgr.es/m/apBkixO4xAGFoiT3@nathan Backpatch-through: 19 --- doc/src/sgml/ref/repack.sgml | 6 ++++++ src/backend/commands/repack.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml index d9c7c9e6b95..3c83f529298 100644 --- a/doc/src/sgml/ref/repack.sgml +++ b/doc/src/sgml/ref/repack.sgml @@ -285,6 +285,12 @@ REPACK [ ( option [, ...] ) ] USING + + + The table's access method is not heap. + + + REPACK is executed inside a transaction block. diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 89aa038d23d..7cba8bece9c 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -888,6 +888,20 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errdetail("%s requires \"wal_level\" to be set to \"replica\" or higher.", "REPACK (CONCURRENTLY)")); + /* + * A table AM that doesn't support logical decoding would cause REPACK + * (CONCURRENTLY) to silently lose the changes made during the rewrite. + * Nothing in TableAmRoutine tells us whether it does, so for now restrict + * to heap. Check the routine rather than the AM OID, so that an AM + * reusing the heap handler still works. + */ + if (rel->rd_tableam != GetHeapamTableAmRoutine()) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), + errdetail("This operation is only supported for the \"heap\" access method.")); + /* Data changes in system relations are not logically decoded. */ if (IsCatalogRelation(rel)) ereport(ERROR, -- 2.47.3