On Mon, Aug 31, 2026 at 8:35 PM Bharath Rupireddy
<[email protected]> wrote:
>
> Hi,
>
> On Sat, Aug 29, 2026 at 8:34 AM Bharath Rupireddy
> <[email protected]> wrote:
> >
> > Hi,
> >
> > On Sat, Aug 29, 2026 at 4:23 AM Antonin Houska <[email protected]> wrote:
> > >
> > > Thanks! I'm just thinking about this comment:
> > >
> > > +       /* The CONCURRENTLY path does not write logical rewrite mappings. 
> > > */
> > >
> > > IMO it makes no sense to rewrite the logical mappings as long as REPACK
> > > (CONCURRENTLY) changes visibility information (i.e. it's MVCC-unsafe). 
> > > Once we
> > > implement the MVCC-safety, we should not remove this check unless we 
> > > implement
> > > the rewriting of the mappings for user catalog tables - that might also be
> > > worth mentioning in the comment.
> > >
> > > So far, I'd consider the MVCC-unsafety the primary reason to prohibit 
> > > REPACK
> > > (CONCURRENTLY) (or anyother MVCC-unsafe command) on the user catalog 
> > > tables,
> > > because it can make the contents of those tables invisible to the output
> > > plugin at some point.
> >
> > Thanks for pointing this out. I read the docs related to MVCC-safety
> > of concurrent repack. I reworded the comment as you suggested. Feel
> > free to suggest changes to it if any. Please find the attached v2
> > patch.
>
> Please find the attached v3 patch with a test added similar to other
> restricted error cases. Sorry for the noise.

I reviewed the patch. It's simple and I agree to add a check for user
catalog tables. I've slightly rephrased the comment in
check_concurrent_repack_requirements() to clarify the reason why
REPACK (CONCURRENTLY) doesn't support user catalog tables while it
does for normal tables even though it's a MVCC-unsafe operation. Also
updated the commit message as well. Please review it.

Regards,


--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com
From f54f13e29b56fde249c96ffeb3d5044239f6927c Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <[email protected]>
Date: Tue, 1 Sep 2026 03:20:50 +0000
Subject: [PATCH v4] Restrict REPACK (CONCURRENTLY) on user catalog tables.

REPACK (CONCURRENTLY) is not an MVCC-safe operation; it doesn't
preserve the visibility information, which logical decoding needs
because it reads user catalog tables under a historic snapshot.

Disallow REPACK (CONCURRENTLY) on user catalog tables. Removing this
check requires making it MVCC-safe and logical rewrite mappings.

Backpatch to v19, where REPACK (CONCURRENTLY) was introduced.

Reported-by: Nathan Bossart <[email protected]>
Author: Bharath Rupireddy <[email protected]>
Reviewed-by: Antonin Houska <[email protected]>
Reviewed-by: Masahiko Sawada <[email protected]>
Discussion: https://postgr.es/m/apBIFWzHYOaG0auN%40nathan
Backpatch-through: 19
---
 contrib/test_decoding/expected/repack.out |  6 ++++++
 contrib/test_decoding/sql/repack.sql      |  5 +++++
 doc/src/sgml/ref/repack.sgml              |  8 ++++++++
 src/backend/commands/repack.c             | 14 ++++++++++++++
 4 files changed, 33 insertions(+)

diff --git a/contrib/test_decoding/expected/repack.out b/contrib/test_decoding/expected/repack.out
index 5ddc63238c5..6ed0af0f8ad 100644
--- a/contrib/test_decoding/expected/repack.out
+++ b/contrib/test_decoding/expected/repack.out
@@ -61,6 +61,12 @@ HINT:  Consider running the command on individual partitions.
 REPACK (CONCURRENTLY) pg_class;
 ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "pg_class"
 HINT:  REPACK (CONCURRENTLY) is not supported for catalog relations.
+-- Doesn't support tables used as catalog tables
+CREATE TABLE repack_conc_user_catalog (i int) WITH (user_catalog_table = true);
+REPACK (CONCURRENTLY) repack_conc_user_catalog;
+ERROR:  cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_user_catalog"
+HINT:  REPACK (CONCURRENTLY) is not supported for tables used as catalog tables.
+DROP TABLE repack_conc_user_catalog;
 -- Doesn't support TOAST tables directly
 CREATE TABLE repack_conc_toast (t text);
 SELECT reltoastrelid::regclass AS toast_rel
diff --git a/contrib/test_decoding/sql/repack.sql b/contrib/test_decoding/sql/repack.sql
index f461f5479f4..eb891009baf 100644
--- a/contrib/test_decoding/sql/repack.sql
+++ b/contrib/test_decoding/sql/repack.sql
@@ -42,6 +42,11 @@ REPACK (CONCURRENTLY) clstrpart;
 -- Disallowed in catalogs
 REPACK (CONCURRENTLY) pg_class;
 
+-- Doesn't support tables used as catalog tables
+CREATE TABLE repack_conc_user_catalog (i int) WITH (user_catalog_table = true);
+REPACK (CONCURRENTLY) repack_conc_user_catalog;
+DROP TABLE repack_conc_user_catalog;
+
 -- Doesn't support TOAST tables directly
 CREATE TABLE repack_conc_toast (t text);
 SELECT reltoastrelid::regclass AS toast_rel
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 [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
         </para>
        </listitem>
 
+       <listitem>
+        <para>
+          The table is declared as a catalog table using the
+          <link linkend="reloption-user-catalog-table"><literal>user_catalog_table</literal></link>
+          storage parameter.
+        </para>
+       </listitem>
+
        <listitem>
         <para>
          <command>REPACK</command> is executed inside a transaction block.
diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index 477c86b2ba6..b42fda303a2 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -886,6 +886,20 @@ 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; it doesn't preserve visibility
+	 * information, which logical decoding needs because it reads user catalog
+	 * tables under a historic snapshot. Removing this check requires making
+	 * it MVCC-safe and logical rewrite mappings.
+	 */
+	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.55.0

Reply via email to