From 3d9151c368b16f8ec01dccb4081d4880511da057 Mon Sep 17 00:00:00 2001
From: Baji Shaik <baji.pgdev@gmail.com>
Date: Tue, 26 May 2026 21:36:03 -0500
Subject: [PATCH 2/3] Improve REPACK (CONCURRENTLY) errors for unusable
 identity

In check_concurrent_repack_requirements(), GetRelationIdentityOrPK()
returns InvalidOid for several distinct reasons but the user sees the
same generic 'has no identity index' error in all of them.  Two of
those cases give misleading guidance:

  - REPLICA IDENTITY FULL is set, but the hint says the relation has
    no identity index.
  - The only primary key is DEFERRABLE (skipped per commit 832e220d99a),
    but the hint suggests adding an index that already exists.

Distinguish these two cases with specific messages.  The third case
(no identity at all) keeps the existing message.

The new branches use information already on the Relation struct
(relreplident, rd_ispkdeferrable, rd_pkindex).
---
 src/backend/commands/repack.c         | 29 +++++++++++++++++++++++++++
 src/test/regress/expected/cluster.out |  5 +++--
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index 3d5bd98ad5f..e2d405c336f 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -959,12 +959,41 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p)
 	 */
 	ident_idx = GetRelationIdentityOrPK(rel);
 	if (!OidIsValid(ident_idx))
+	{
+		/*
+		 * GetRelationIdentityOrPK() returns InvalidOid in several distinct
+		 * cases.  Distinguish them so the user sees an actionable message:
+		 *
+		 *   - REPLICA IDENTITY FULL is set: not yet supported.
+		 *   - The relation has a deferrable primary key as its only
+		 *     identity: REPACK ignores deferrable PKs (see commit
+		 *     832e220d99a).
+		 *   - The relation has no identity index of any kind.
+		 */
+		if (replident == REPLICA_IDENTITY_FULL)
+			ereport(ERROR,
+					errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					errmsg("cannot repack relation \"%s\"",
+						   RelationGetRelationName(rel)),
+					errdetail("%s does not support tables with REPLICA IDENTITY FULL.",
+							  "REPACK (CONCURRENTLY)"));
+
+		if (rel->rd_ispkdeferrable && OidIsValid(rel->rd_pkindex))
+			ereport(ERROR,
+					errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+					errmsg("cannot repack relation \"%s\"",
+						   RelationGetRelationName(rel)),
+					errdetail("%s does not support a deferrable primary key as identity.",
+							  "REPACK (CONCURRENTLY)"),
+					errhint("Use ALTER TABLE ... ALTER CONSTRAINT to make the primary key NOT DEFERRABLE, or use ALTER TABLE ... REPLICA IDENTITY USING INDEX to designate another index."));
+
 		ereport(ERROR,
 				errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 				errmsg("cannot process relation \"%s\"",
 					   RelationGetRelationName(rel)),
 				errhint("Relation \"%s\" has no identity index.",
 						RelationGetRelationName(rel)));
+	}
 
 	*ident_idx_p = ident_idx;
 }
diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out
index 504ac1a3131..48667547060 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -846,8 +846,9 @@ HINT:  Relation "repack_conc_replident" has no identity index.
 -- Doesn't support tables with deferrable primary keys
 ALTER TABLE repack_conc_replident ADD PRIMARY KEY (i) DEFERRABLE;
 REPACK (CONCURRENTLY) repack_conc_replident;
-ERROR:  cannot process relation "repack_conc_replident"
-HINT:  Relation "repack_conc_replident" has no identity index.
+ERROR:  cannot repack relation "repack_conc_replident"
+DETAIL:  REPACK (CONCURRENTLY) does not support a deferrable primary key as identity.
+HINT:  Use ALTER TABLE ... ALTER CONSTRAINT to make the primary key NOT DEFERRABLE, or use ALTER TABLE ... REPLICA IDENTITY USING INDEX to designate another index.
 -- clean up
 DROP TABLE repack_conc_replident;
 DROP TABLE clustertest;
-- 
2.50.1 (Apple Git-155)

