diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 94f2eaa2346..ec100e3eef5 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -901,7 +901,7 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) if (wal_level < WAL_LEVEL_REPLICA) ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("cannot execute \"%s\" in this configuration", + errmsg("cannot execute %s in this configuration", "REPACK (CONCURRENTLY)"), errdetail("%s requires \"wal_level\" to be set to \"replica\" or higher.", "REPACK (CONCURRENTLY)")); @@ -910,8 +910,8 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) if (IsCatalogRelation(rel)) ereport(ERROR, errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot repack relation \"%s\"", - RelationGetRelationName(rel)), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), errhint("%s is not supported for catalog relations.", "REPACK (CONCURRENTLY)")); @@ -922,8 +922,8 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) if (IsToastRelation(rel)) ereport(ERROR, errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot repack relation \"%s\"", - RelationGetRelationName(rel)), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), errhint("%s is not supported for TOAST relations.", "REPACK (CONCURRENTLY)")); @@ -931,20 +931,26 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) if (relpersistence != RELPERSISTENCE_PERMANENT) ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("cannot repack relation \"%s\"", - RelationGetRelationName(rel)), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), errhint("%s is only allowed for permanent relations.", "REPACK (CONCURRENTLY)")); - /* With NOTHING, WAL does not contain the old tuple. */ + /* + * With NOTHING, WAL does not contain the old tuple; FULL is not yet + * supported. + */ replident = rel->rd_rel->relreplident; - if (replident == REPLICA_IDENTITY_NOTHING) + if (replident == REPLICA_IDENTITY_NOTHING || + replident == REPLICA_IDENTITY_FULL) ereport(ERROR, errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("cannot repack relation \"%s\"", - RelationGetRelationName(rel)), - errhint("Relation \"%s\" has insufficient replication identity.", - RelationGetRelationName(rel))); + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", RelationGetRelationName(rel)), + errdetail("%s does not support tables with %s.", + "REPACK (CONCURRENTLY)", + replident == REPLICA_IDENTITY_NOTHING ? + "REPLICA IDENTITY NOTHING" : "REPLICA IDENTITY FULL")); /* * Obtain the replica identity index -- either one that has been set @@ -955,12 +961,25 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p) */ ident_idx = GetRelationIdentityOrPK(rel); if (!OidIsValid(ident_idx)) + { + /* This special case warrants its own error message */ + if (OidIsValid(rel->rd_pkindex) && rel->rd_ispkdeferrable) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", + RelationGetRelationName(rel)), + errdetail("%s does not support deferrable primary keys.", + "REPACK (CONCURRENTLY)"), + 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 process relation \"%s\"", - RelationGetRelationName(rel)), + errmsg("cannot execute %s on relation \"%s\"", + "REPACK (CONCURRENTLY)", 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..23f312c62a3 100644 --- a/src/test/regress/expected/cluster.out +++ b/src/test/regress/expected/cluster.out @@ -801,7 +801,7 @@ ORDER BY o.relname; -- -- Disallowed in catalogs REPACK (CONCURRENTLY) pg_class; -ERROR: cannot repack relation "pg_class" +ERROR: cannot execute REPACK (CONCURRENTLY) on relation "pg_class" HINT: REPACK (CONCURRENTLY) is not supported for catalog relations. -- Doesn't like partitioned tables REPACK (CONCURRENTLY) clstrpart; @@ -809,17 +809,17 @@ ERROR: REPACK (CONCURRENTLY) is not supported for partitioned tables HINT: Consider running the command on individual partitions. -- Doesn't support catalog tables REPACK (CONCURRENTLY) pg_class; -ERROR: cannot repack relation "pg_class" +ERROR: cannot execute REPACK (CONCURRENTLY) on relation "pg_class" HINT: REPACK (CONCURRENTLY) is not supported for catalog relations. -- Only support permanent tables, temp and unlogged tables are not supported CREATE TEMP TABLE repack_conc_temp (i int PRIMARY KEY); REPACK (CONCURRENTLY) repack_conc_temp; -ERROR: cannot repack relation "repack_conc_temp" +ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_temp" HINT: REPACK (CONCURRENTLY) is only allowed 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 repack relation "repack_conc_unlogged" +ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_unlogged" HINT: REPACK (CONCURRENTLY) is only allowed for permanent relations. DROP TABLE repack_conc_unlogged; -- Doesn't support TOAST tables directly @@ -835,19 +835,20 @@ DROP TABLE repack_conc_toast; CREATE TABLE repack_conc_replident (i int PRIMARY KEY); ALTER TABLE repack_conc_replident REPLICA IDENTITY NOTHING; REPACK (CONCURRENTLY) repack_conc_replident; -ERROR: cannot repack relation "repack_conc_replident" -HINT: Relation "repack_conc_replident" has insufficient replication identity. +ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident" +DETAIL: REPACK (CONCURRENTLY) 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 process relation "repack_conc_replident" +ERROR: cannot execute REPACK (CONCURRENTLY) on relation "repack_conc_replident" 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 execute REPACK (CONCURRENTLY) on relation "repack_conc_replident" +DETAIL: REPACK (CONCURRENTLY) 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; DROP TABLE clustertest;