Thanks for the review,
I've updated the patch to address your comments:
- Documented that 'REPACK (ANALYZE)' cannot be used inside a transaction
block, or from a function, procedure or 'DO' block.
- Updated the comment in repack.c to clarify that this restriction is
intentional for now, consistently with VACUUM (FULL, ANALYZE).
- Added regression tests covering plain REPACK inside a transaction
block; REPACK (ANALYZE) inside a transaction block; REPACK (ANALYZE)
from a DO block.
- Regenerated 'expected/cluster.out.
The focused 'test_setup' and 'cluster' regression tests pass, and the patch
applies cleanly to the current tree.
The updated patch is attached.
With regards,
Osama Abdul Qader
On Thu, Sep 3, 2026 at 9:59 PM Osama Abdul Qader <
[email protected]> wrote:
> Good Evening Masao San
>
> Thanks for the detailed review.
>
> I understood and I'll update the patch to:
>
>
> - document the transaction-block restriction in repack documentation.
> - revise the comment in 'repack.c' to reflect that this is an
> intentional restriction for v19, rather than an inherent requirement; and
> - expand the regression tests to cover plain REPACK inside a
> transaction block, REPACK (ANALYZE) inside a transaction block, and REPACK
> (ANALYZE) from a DO block.
>
> I'll send an updated patch once these changes are made.
>
> With regards,
> Osama Abdul Qader
>
> On Thu, 3 Sept, 2026, 7:21 pm Fujii Masao, <[email protected]> wrote:
>
>> On Thu, Sep 3, 2026 at 5:27 PM Osama Abdul Qader
>> <[email protected]> wrote:
>> > The updated patch is attached.
>>
>> Thanks for updating the patch!
>>
>> I have a few review comments.
>>
>> As I told upthread, I think the restriction that REPACK (ANALYZE) cannot
>> be executed inside a transaction block should be documented. For example,
>> how about adding something like the following to the description of
>> the ANALYZE option in the REPACK docs?
>>
>> This option cannot be used inside a transaction block, or from a
>> function, procedure, or <command>DO</command> block.
>>
>>
>> + * It therefore cannot be executed inside a transaction block or
>>
>> Is this really true? As discussed upthread, I was thinking that it can
>> be executed even inside a transaction block, but that we decided to
>> intentionally prevent it from doing so to match the behavior of
>> VACUUM (FULL, ANALYZE) as the safe behavior for v19. No?
>>
>>
>> Regarding the tests, as I told upthread, I think it's better to also
>> cover the following cases:
>>
>> - plain REPACK is allowed in a transaction block
>> - REPACK (ANALYZE) is not allowed from a function
>>
>> For example:
>>
>> -------------------------
>> --- Verify partial analyze works
>> +-- Verify REPACK (ANALYZE) works, including partial analyze.
>> REPACK (ANALYZE) clstr_tst (a);
>> REPACK (ANALYZE) clstr_tst;
>> +-- Plain REPACK is allowed in a transaction block.
>> +BEGIN;
>> +REPACK clstr_tst;
>> +ROLLBACK;
>> +-- REPACK (ANALYZE) is not allowed in a transaction block.
>> +BEGIN;
>> +REPACK (ANALYZE) clstr_tst;
>> +ROLLBACK;
>> +-- REPACK (ANALYZE) is not allowed from a function.
>> +DO $$ BEGIN EXECUTE 'REPACK (ANALYZE) clstr_tst'; END $$;
>> -------------------------
>>
>> Regards,
>>
>>
>> --
>> Fujii Masao
>>
>
diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml
index 0cb72b6b289..d9c7c9e6b95 100644
--- a/doc/src/sgml/ref/repack.sgml
+++ b/doc/src/sgml/ref/repack.sgml
@@ -329,6 +329,8 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
<para>
Applies <xref linkend="sql-analyze"/> on the table after repacking. This is
currently only supported when a single (non-partitioned) table is specified.
+ This option cannot be used inside a transaction block, or from a function,
+ procedure, or <command>DO</command> block.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index edff54e734e..c1ee5cdd37f 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -314,6 +314,15 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
PreventInTransactionBlock(isTopLevel, "REPACK (CONCURRENTLY)");
}
+ else if ((params.options & CLUOPT_ANALYZE) != 0)
+ {
+ /*
+ * REPACK (ANALYZE) is not allowed in a transaction block for now,
+ * consistently with VACUUM (FULL, ANALYZE).
+ */
+ PreventInTransactionBlock(isTopLevel, "REPACK (ANALYZE)");
+ }
+
/*
* If a single relation is specified, process it and we're done ... unless
* the relation is a partitioned table, in which case we fall through.
diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out
index d1bc8a13286..9ad7e2e21c0 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -796,9 +796,23 @@ ORDER BY 1;
clstr_tst_pkey
(3 rows)
--- Verify partial analyze works
+-- Verify REPACK (ANALYZE) works, including partial analyze.
REPACK (ANALYZE) clstr_tst (a);
REPACK (ANALYZE) clstr_tst;
+-- Plain REPACK is allowed in a transaction block.
+BEGIN;
+REPACK clstr_tst;
+ROLLBACK;
+-- REPACK (ANALYZE) is not allowed in a transaction block.
+BEGIN;
+REPACK (ANALYZE) clstr_tst;
+ERROR: REPACK (ANALYZE) cannot run inside a transaction block
+ROLLBACK;
+-- REPACK (ANALYZE) is not allowed from a function.
+DO $$ BEGIN EXECUTE 'REPACK (ANALYZE) clstr_tst'; END $$;
+ERROR: REPACK (ANALYZE) cannot be executed from a function or procedure
+CONTEXT: SQL statement "REPACK (ANALYZE) clstr_tst"
+PL/pgSQL function inline_code_block line 1 at EXECUTE
REPACK (VERBOSE) clstr_tst (a);
ERROR: ANALYZE option must be specified when a column list is provided
-- REPACK w/o argument performs no ordering, so we can only check which tables
diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql
index e7a62367adf..dcc91e73698 100644
--- a/src/test/regress/sql/cluster.sql
+++ b/src/test/regress/sql/cluster.sql
@@ -380,9 +380,23 @@ INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass
ORDER BY 1;
--- Verify partial analyze works
+-- Verify REPACK (ANALYZE) works, including partial analyze.
REPACK (ANALYZE) clstr_tst (a);
REPACK (ANALYZE) clstr_tst;
+
+-- Plain REPACK is allowed in a transaction block.
+BEGIN;
+REPACK clstr_tst;
+ROLLBACK;
+
+-- REPACK (ANALYZE) is not allowed in a transaction block.
+BEGIN;
+REPACK (ANALYZE) clstr_tst;
+ROLLBACK;
+
+-- REPACK (ANALYZE) is not allowed from a function.
+DO $$ BEGIN EXECUTE 'REPACK (ANALYZE) clstr_tst'; END $$;
+
REPACK (VERBOSE) clstr_tst (a);
-- REPACK w/o argument performs no ordering, so we can only check which tables