From 71301630532b8aa8bb0e031b3c0b90a5365b4c25 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Sat, 29 Aug 2026 15:15:47 +0000 Subject: [PATCH v2] Restrict REPACK (CONCURRENTLY) on user catalog tables. Commit 28d534e2ae0 added the CONCURRENTLY option to REPACK. Unlike the default path, which rewrites the table through rewriteheap.c, the concurrent path is not MVCC-safe: it changes the visibility information of the tuples it rewrites. A table declared with the user_catalog_table storage parameter is read by an output plugin during logical decoding, using historical snapshots. Changing that visibility information can make the table's contents invisible to the plugin at some point, silently breaking decoding. check_concurrent_repack_requirements() already rejects system catalogs but did not consider tables used as catalog tables. Reject those too, the same way a table rewrite via ALTER TABLE already does, and document the limitation. Once REPACK (CONCURRENTLY) is made MVCC-safe, this check should stay unless the rewrite mappings are also written for user catalog tables. Backpatch to v19, where REPACK (CONCURRENTLY) was introduced. Reported-by: Nathan Bossart Author: Bharath Rupireddy Reviewed-by: Antonin Houska Discussion: https://postgr.es/m/apBIFWzHYOaG0auN%40nathan Backpatch-through: 19 --- doc/src/sgml/ref/repack.sgml | 8 ++++++++ src/backend/commands/repack.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml index 0cb72b6b289..e2d5a34ba8b 100644 --- a/doc/src/sgml/ref/repack.sgml +++ b/doc/src/sgml/ref/repack.sgml @@ -285,6 +285,14 @@ REPACK [ ( option [, ...] ) ] USING + + + The table is declared as a catalog table using the + user_catalog_table + storage parameter. + + + REPACK is executed inside a transaction block. diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 477c86b2ba6..829f76ac1d5 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -886,6 +886,21 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errhint("%s is not supported for catalog relations.", "REPACK (CONCURRENTLY)")); + /* + * REPACK (CONCURRENTLY) is not MVCC-safe, i.e. it changes visibility + * information, which can make the contents invisible to the output + * plugin. Once it is made MVCC-safe, the logical rewrite mappings must + * also be written for user catalog tables before this check can be + * removed. + */ + if (RelationIsUsedAsCatalogTable(rel)) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), + errhint("%s is not supported for tables used as catalog tables.", + "REPACK (CONCURRENTLY)")); + /* * reorderbuffer.c does not seem to handle processing of TOAST relation * alone. -- 2.47.3