From 97d1b2023b8c4ac5d92610e9761d112ab68cbe23 Mon Sep 17 00:00:00 2001 From: Jim Jones Date: Wed, 25 Mar 2026 23:30:55 +0100 Subject: [PATCH v3 2/2] Test VACUUM FULL, CLUSTER, and REPACK with locked temp tables This test creates a background session with a temp table and marks its index as clustered (making it visible to both the pg_class scan used by VACUUM FULL and REPACK, and the pg_index scan used by CLUSTER), then holds ACCESS SHARE LOCK in an open transaction. Each command runs with lock_timeout = '1ms'. Since lock_timeout only fires when a backend actually blocks waiting for a lock, 1ms is sufficient. --- src/test/modules/test_misc/meson.build | 1 + .../t/011_vacuum_cluster_temp_tables.pl | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/test/modules/test_misc/t/011_vacuum_cluster_temp_tables.pl diff --git a/src/test/modules/test_misc/meson.build b/src/test/modules/test_misc/meson.build index 6e8db1621a7..d64e8df56bf 100644 --- a/src/test/modules/test_misc/meson.build +++ b/src/test/modules/test_misc/meson.build @@ -19,6 +19,7 @@ tests += { 't/008_replslot_single_user.pl', 't/009_log_temp_files.pl', 't/010_index_concurrently_upsert.pl', + 't/011_vacuum_cluster_temp_tables.pl', ], # The injection points are cluster-wide, so disable installcheck 'runningcheck': false, diff --git a/src/test/modules/test_misc/t/011_vacuum_cluster_temp_tables.pl b/src/test/modules/test_misc/t/011_vacuum_cluster_temp_tables.pl new file mode 100644 index 00000000000..a612b4d6361 --- /dev/null +++ b/src/test/modules/test_misc/t/011_vacuum_cluster_temp_tables.pl @@ -0,0 +1,65 @@ +# Copyright (c) 2026, PostgreSQL Global Development Group +# +# Verify that no-argument VACUUM FULL, CLUSTER, and REPACK skip temporary +# tables belonging to other sessions. +# +# A background session creates a temp table and marks its index as clustered — +# making it visible to both the pg_class scan (VACUUM FULL, REPACK) and the +# pg_index scan (CLUSTER) — then holds ACCESS SHARE LOCK in an open transaction. +# Each command runs with lock_timeout = '1ms'. Since lock_timeout only +# fires when a backend actually blocks waiting for a lock, 1ms is sufficient. + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +my $node = PostgreSQL::Test::Cluster->new('vacuum_cluster_temp'); +$node->init; +$node->start; + +# Session 1: build the temp table and hold a conflicting lock. +my $psql1 = $node->background_psql('postgres'); + +$psql1->query_safe( + q{CREATE TEMP TABLE temp_repack_test (val int); + INSERT INTO temp_repack_test VALUES (1); + CREATE INDEX temp_repack_idx ON temp_repack_test (val); + CLUSTER temp_repack_test USING temp_repack_idx;}); + +$psql1->query_safe(q{BEGIN}); +$psql1->query_safe(q{LOCK TABLE temp_repack_test IN ACCESS SHARE MODE}); + +my ($stdout, $stderr, $ret); + +# VACUUM FULL — pg_class scan path. +$ret = $node->psql( + 'postgres', + "SET lock_timeout = '1ms'; VACUUM FULL;", + stdout => \$stdout, + stderr => \$stderr); +is($ret, 0, + 'VACUUM FULL completes without blocking on another session temp table'); + +# CLUSTER — pg_index scan path (indisclustered entries). +$ret = $node->psql( + 'postgres', + "SET lock_timeout = '1ms'; CLUSTER;", + stdout => \$stdout, + stderr => \$stderr); +is($ret, 0, + 'CLUSTER completes without blocking on another session temp table'); + +# REPACK — pg_class scan path. +$ret = $node->psql( + 'postgres', + "SET lock_timeout = '1ms'; REPACK;", + stdout => \$stdout, + stderr => \$stderr); +is($ret, 0, + 'REPACK completes without blocking on another session temp table'); + +$psql1->quit; + +done_testing(); -- 2.43.0