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

Reply via email to