1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Reject REPACK (ANALYZE) in a transaction block

The current implementation doesn't support it correctly, leading to
mysterious warnings and some worse problems.  Have the combination throw
an error.

This is intended as a temporary stopgap until we can implement it in a
future release, as it's a useful feature.

Author: Fujii Masao <masao.fujii@gmail.com>
Author: Antonin Houska <ah@cybertec.at>
Author: Osama Abdul Qader <osamaabdulqader.cs@gmail.com>
Reported-by: Nathan Bossart <nathandbossart@gmail.com>
Backpatch-through: 19
Discussion: https://postgr.es/m/apBCEl4hBHlq0axm@nathan
This commit is contained in:
Álvaro Herrera
2026-09-08 14:06:06 +02:00
parent d0518cb3e4
commit 24dd8c369e
4 changed files with 46 additions and 3 deletions

View File

@@ -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>

View File

@@ -303,7 +303,7 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
if ((params.options & CLUOPT_CONCURRENT) != 0)
{
/*
* Make sure we're not in a transaction block.
* In concurrent mode, make sure we're not in a transaction block.
*
* The reason is that repack_setup_logical_decoding() could wait
* indefinitely for our XID to complete. (The deadlock detector would
@@ -314,6 +314,17 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
*/
PreventInTransactionBlock(isTopLevel, "REPACK (CONCURRENTLY)");
}
else if ((params.options & CLUOPT_ANALYZE) != 0)
{
/*
* With ANALYZE, process_single_relation() would commit the current
* transaction and start a new one, which would break our state if
* we're in a transaction block or PL-execution environment. Reject
* the option in that case. It may be possible to remove this
* restriction in the future.
*/
PreventInTransactionBlock(isTopLevel, "REPACK (ANALYZE)");
}
/*
* If a single relation is specified, process it and we're done ... unless

View File

@@ -796,9 +796,24 @@ 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 is allowed within a PL, as long as there's no ANALYZE.
DO $$ BEGIN EXECUTE 'REPACK clstr_tst'; END $$;
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

View File

@@ -380,9 +380,24 @@ 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 is allowed within a PL, as long as there's no ANALYZE.
DO $$ BEGIN EXECUTE 'REPACK clstr_tst'; END $$;
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