1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-25 01:39:28 +03:00

Restrict REPACK (CONCURRENTLY) to the heap access method.

REPACK (CONCURRENTLY) didn't check the table AM of the table being
repacked, so if the table AM doesn't support logical decoding, the
concurrent changes are never decoded and are silently lost from the
rewritten table.

Fix by erroring out for tables that use a non-heap access method.

Reported-by: Nathan Bossart <nathandbossart@gmail.com>
Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
Discussion: https://postgr.es/m/apBkixO4xAGFoiT3@nathan
Backpatch-through: 19
This commit is contained in:
Masahiko Sawada
2026-09-08 11:49:11 -07:00
parent 11fb89fdbd
commit e8636f2bed
2 changed files with 20 additions and 0 deletions

View File

@@ -285,6 +285,12 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
</para>
</listitem>
<listitem>
<para>
The table's access method is not <literal>heap</literal>.
</para>
</listitem>
<listitem>
<para>
<command>REPACK</command> is executed inside a transaction block.

View File

@@ -888,6 +888,20 @@ check_concurrent_repack_requirements(Relation rel, Oid *ident_idx_p)
errdetail("%s requires \"wal_level\" to be set to \"replica\" or higher.",
"REPACK (CONCURRENTLY)"));
/*
* A table AM that doesn't support logical decoding would cause REPACK
* (CONCURRENTLY) to silently lose the changes made during the rewrite.
* Nothing in TableAmRoutine tells us whether it does, so for now restrict
* to heap. Check the routine rather than the AM OID, so that an AM
* reusing the heap handler still works.
*/
if (rel->rd_tableam != GetHeapamTableAmRoutine())
ereport(ERROR,
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot execute %s on relation \"%s\"",
"REPACK (CONCURRENTLY)", RelationGetRelationName(rel)),
errdetail("This operation is only supported for the \"heap\" access method."));
/* Data changes in system relations are not logically decoded. */
if (IsCatalogRelation(rel))
ereport(ERROR,