From fe7b60723420c5279824c35efc45630889239a70 Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Tue, 8 Sep 2026 11:49:14 -0700 Subject: [PATCH] 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,