From 4964c75b0889ab79a268dc1e1027e4dabe0c7dfd Mon Sep 17 00:00:00 2001 From: Masahiko Sawada Date: Wed, 9 Sep 2026 13:45:43 -0700 Subject: [PATCH] Unify REPACK (CONCURRENTLY) error messages. Commit 86f7c82cf102 reported the user catalog table restriction as a detail, but the other checks in check_concurrent_repack_requirements() were still a mix: some were hints, and the details repeated "REPACK (CONCURRENTLY)", which the primary message already names. Report them as details with the same "This operation ..." wording. The one actionable hint, ALTER TABLE ... REPLICA IDENTITY USING INDEX, stays. Backpatch to v19, where REPACK (CONCURRENTLY) was introduced. Author: Bharath Rupireddy Suggested-by: Alvaro Herrera Discussion: https://postgr.es/m/apBIFWzHYOaG0auN%40nathan Backpatch-through: 19 --- contrib/test_decoding/expected/repack.out | 12 ++++++------ src/backend/commands/repack.c | 22 ++++++++-------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/contrib/test_decoding/expected/repack.out b/contrib/test_decoding/expected/repack.out index 2dd3891b869..ac5473137d1 100644 --- a/contrib/test_decoding/expected/repack.out +++ b/contrib/test_decoding/expected/repack.out @@ -60,7 +60,7 @@ HINT: Consider running the command on individual partitions. -- Disallowed in catalogs REPACK (CONCURRENTLY) pg_class; ERROR: cannot execute REPACK (CONCURRENTLY) on relation "pg_class" -HINT: REPACK (CONCURRENTLY) is not supported for catalog relations. +DETAIL: This operation is not supported for system catalogs. -- 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; @@ -80,12 +80,12 @@ DROP TABLE repack_conc_toast; CREATE TEMP TABLE repack_conc_temp (i int PRIMARY KEY); REPACK (CONCURRENTLY) repack_conc_temp; ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_temp" -HINT: REPACK (CONCURRENTLY) is only allowed for permanent relations. +DETAIL: This operation is only supported for permanent relations. DROP TABLE repack_conc_temp; CREATE UNLOGGED TABLE repack_conc_unlogged (i int PRIMARY KEY); REPACK (CONCURRENTLY) repack_conc_unlogged; ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_unlogged" -HINT: REPACK (CONCURRENTLY) is only allowed for permanent relations. +DETAIL: This operation is only supported for permanent relations. DROP TABLE repack_conc_unlogged; -- Doesn't support materialized views CREATE MATERIALIZED VIEW repack_conc_matview AS SELECT 1 AS i; @@ -98,18 +98,18 @@ CREATE TABLE repack_conc_replident (i int PRIMARY KEY); ALTER TABLE repack_conc_replident REPLICA IDENTITY NOTHING; REPACK (CONCURRENTLY) repack_conc_replident; ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident" -DETAIL: REPACK (CONCURRENTLY) does not support tables with REPLICA IDENTITY NOTHING. +DETAIL: This operation does not support tables with REPLICA IDENTITY NOTHING. -- Doesn't support tables without a primary key or replica identity index ALTER TABLE repack_conc_replident DROP CONSTRAINT repack_conc_replident_pkey; ALTER TABLE repack_conc_replident REPLICA IDENTITY DEFAULT; REPACK (CONCURRENTLY) repack_conc_replident; ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident" -HINT: Relation "repack_conc_replident" has no identity index. +DETAIL: 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 execute REPACK (CONCURRENTLY) on relation "repack_conc_replident" -DETAIL: REPACK (CONCURRENTLY) does not support deferrable primary keys. +DETAIL: This operation does not support deferrable primary keys. HINT: Use ALTER TABLE ... REPLICA IDENTITY USING INDEX to designate another index as replica identity. -- clean up DROP TABLE repack_conc_replident, clstrpart; diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 4521ccd036f..0533217968e 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -885,8 +885,7 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot execute %s in this configuration", "REPACK (CONCURRENTLY)"), - errdetail("%s requires \"wal_level\" to be set to \"replica\" or higher.", - "REPACK (CONCURRENTLY)")); + errdetail("This operation requires \"wal_level\" to be set to \"replica\" or higher.")); /* * A table AM that doesn't support logical decoding would cause REPACK @@ -908,8 +907,7 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot execute %s on relation \"%s\"", "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), - errhint("%s is not supported for catalog relations.", - "REPACK (CONCURRENTLY)")); + errdetail("This operation is not supported for system catalogs.")); /* * REPACK (CONCURRENTLY) is not MVCC-safe; it doesn't preserve visibility @@ -933,8 +931,7 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot execute %s on relation \"%s\"", "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), - errhint("%s is not supported for TOAST relations.", - "REPACK (CONCURRENTLY)")); + errdetail("This operation is not supported for TOAST tables.")); relpersistence = rel->rd_rel->relpersistence; if (relpersistence != RELPERSISTENCE_PERMANENT) @@ -942,8 +939,7 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot execute %s on relation \"%s\"", "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), - errhint("%s is only allowed for permanent relations.", - "REPACK (CONCURRENTLY)")); + errdetail("This operation is only supported for permanent relations.")); /* A materialized view produces no logically decoded changes. */ if (rel->rd_rel->relkind == RELKIND_MATVIEW) @@ -964,8 +960,7 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot execute %s on relation \"%s\"", "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), - errdetail("%s does not support tables with %s.", - "REPACK (CONCURRENTLY)", + errdetail("This operation does not support tables with %s.", replident == REPLICA_IDENTITY_NOTHING ? "REPLICA IDENTITY NOTHING" : "REPLICA IDENTITY FULL")); @@ -986,16 +981,15 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) errmsg("cannot execute %s on relation \"%s\"", "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), - errdetail("%s does not support deferrable primary keys.", - "REPACK (CONCURRENTLY)"), + errdetail("This operation does not support deferrable primary keys."), errhint("Use ALTER TABLE ... REPLICA IDENTITY USING INDEX to designate another index as replica identity.")); ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("cannot execute %s on relation \"%s\"", "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), - errhint("Relation \"%s\" has no identity index.", - RelationGetRelationName(rel))); + errdetail("Relation \"%s\" has no identity index.", + RelationGetRelationName(rel))); } *ident_idx_p = ident_idx;