Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wFTvo-005B7p-16 for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2026 09:31:40 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wFTuo-00CjgR-1r for pgsql-hackers@arkaria.postgresql.org; Wed, 22 Apr 2026 09:30:38 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wFTun-00CjgJ-34 for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2026 09:30:38 +0000 Received: from fout-b5-smtp.messagingengine.com ([202.12.124.148]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wFTuk-00000002Rss-3KyD for pgsql-hackers@lists.postgresql.org; Wed, 22 Apr 2026 09:30:37 +0000 Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.stl.internal (Postfix) with ESMTP id 069D11D0020D; Wed, 22 Apr 2026 05:30:31 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Wed, 22 Apr 2026 05:30:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm2; t=1776850231; x=1776936631; bh=C pjYIRW4eJwbVeG50wugA7JaVNQ/RqohVBKGfDDSKsA=; b=QRZDRlJHV1XbfXk2F Ppk7WWIvqEjFqkB8j8DGvuCdL2oMk4mCPsYR7M2NjbDjdA7KQhnenElW3iAsqtve LyM0rq4j8TvSCLlYVeJBRch+igh+SRe4dgy8Z/+KHT66wdXvFqTXiLTbdgY60YSL X6nRechpIuggbEuxB/cwVQwPn0ch7XgPgMt/ooyXqb7RQkVdR0j/12bRYaJ3A4PE qWBAPucUUJ1z9aaK2ZGZDDFMRL53XkvSIEhUFPFj43O2nQno7XRMCIosayGn4t6X PHCf+2zEALrygChUYO46fRIZ9BeUHbSC8Vo7NiDMU0ALXZu7LxckxbxKTWsbZB4P tgUKQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefhedrtddtgdeifeeludcutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjug hrpeffhffvvefukfggtggugfgjsehmkeerredttdejnecuhfhrohhmpeetlhhvrghrohcu jfgvrhhrvghrrgcuoegrlhhvhhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorhhgqeenuc ggtffrrghtthgvrhhnpeduleekkefgtddttedtkefguddvieffleetgeejiefhteehkeev feettdduvdfhueenucffohhmrghinhepvghnthgvrhhprhhishgvuggsrdgtohhmnecuve hluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghlvhhhvghr rhgvsegrlhhvhhdrnhhoqdhiphdrohhrghdpnhgspghrtghpthhtohepuddtpdhmohguvg epshhmthhpohhuthdprhgtphhtthhopegrnhgurhgvshesrghnrghrrgiivghlrdguvgdp rhgtphhtthhopegrhhestgihsggvrhhtvggtrdgrthdprhgtphhtthhopegrmhhithdrkh grphhilhgrudeisehgmhgrihhlrdgtohhmpdhrtghpthhtohepsghovghkvgifuhhrmhdo phhoshhtghhrvghssehgmhgrihhlrdgtohhmpdhrtghpthhtohepmhhihhgrihhlnhhikh grlhgrhigvuhesghhmrghilhdrtghomhdprhgtphhtthhopehsrhhinhgrthhhvddufeef sehgmhgrihhlrdgtohhmpdhrtghpthhtohepphhgshhqlhdqhhgrtghkvghrsheslhhish htshdrphhoshhtghhrvghsqhhlrdhorhhgpdhrtghpthhtohepthhglhesshhsshdrphhg hhdrphgrrdhushdprhgtphhtthhopehprhihiigshiesthgvlhhsrghsohhfthdrtghomh X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 22 Apr 2026 05:30:30 -0400 (EDT) Received: by ida.kurilemu.internal (Postfix, from userid 1000) id BBE9DB03231; Wed, 22 Apr 2026 11:30:26 +0200 (CEST) Date: Wed, 22 Apr 2026 11:30:26 +0200 From: Alvaro Herrera To: Tom Lane Cc: Antonin Houska , Justin Pryzby , Mihail Nikalayeu , Andres Freund , Amit Kapila , Srinath Reddy Sadipiralla , Matthias van de Meent , pgsql-hackers@lists.postgresql.org, Robert Treat Subject: Re: Adding REPACK [concurrently] Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="5vljmhsecqh6fok5" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --5vljmhsecqh6fok5 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On 2026-Apr-20, Alvaro Herrera wrote: > There's also contrib/test_decoding. It's somewhat vaguely adjacent, and > the tests aren't _really_ about the decoding part, but of all these > options, it seems the least bad one. Here's a patch that does this. -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ --5vljmhsecqh6fok5 Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0001-Move-REPACK-CONCURRENTLY-test-out-of-stock-regressio.patch" From a64043f31950efa5f63274d6a3e498082ad2b064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= Date: Wed, 22 Apr 2026 11:22:50 +0200 Subject: [PATCH] Move REPACK (CONCURRENTLY) test out of stock regression tests These tests sometimes run with wal_level=minimal, which does not allow to run REPACK (CONCURRENTLY). Move them to test_decoding, which is ensured to run with high enough wal_level. Discussion: https://postgr.es/m/260901.1776696126@sss.pgh.pa.us --- contrib/test_decoding/Makefile | 2 +- contrib/test_decoding/expected/repack.out | 30 +++++++++++++++++++++++ contrib/test_decoding/meson.build | 1 + contrib/test_decoding/sql/repack.sql | 25 +++++++++++++++++++ src/test/regress/expected/cluster.out | 29 +++------------------- src/test/regress/sql/cluster.sql | 13 +++------- 6 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 contrib/test_decoding/expected/repack.out create mode 100644 contrib/test_decoding/sql/repack.sql diff --git a/contrib/test_decoding/Makefile b/contrib/test_decoding/Makefile index acbcaed2feb..0111124399a 100644 --- a/contrib/test_decoding/Makefile +++ b/contrib/test_decoding/Makefile @@ -5,7 +5,7 @@ PGFILEDESC = "test_decoding - example of a logical decoding output plugin" REGRESS = ddl xact rewrite toast permissions decoding_in_xact \ decoding_into_rel binary prepared replorigin time messages \ - spill slot truncate stream stats twophase twophase_stream + repack spill slot truncate stream stats twophase twophase_stream ISOLATION = mxact delayed_startup ondisk_startup concurrent_ddl_dml \ oldest_xmin snapshot_transfer subxact_without_top concurrent_stream \ twophase_snapshot slot_creation_error catalog_change_snapshot \ diff --git a/contrib/test_decoding/expected/repack.out b/contrib/test_decoding/expected/repack.out new file mode 100644 index 00000000000..70039d824af --- /dev/null +++ b/contrib/test_decoding/expected/repack.out @@ -0,0 +1,30 @@ +-- Test REPACK (CONCURRENTLY). +-- This isn't strictly about decoding, but it involves logical decoding +-- and requires to be run under higher than minimal wal_level, so we can't +-- have it in the main regression test suite. +-- Ownership of partitions is checked +CREATE TABLE ptnowner(i int unique not null) PARTITION BY LIST (i); +CREATE INDEX ptnowner_i_idx ON ptnowner(i); +CREATE TABLE ptnowner1 PARTITION OF ptnowner FOR VALUES IN (1); +CREATE ROLE regress_ptnowner; +CREATE TABLE ptnowner2 PARTITION OF ptnowner FOR VALUES IN (2); +ALTER TABLE ptnowner1 OWNER TO regress_ptnowner; +SET SESSION AUTHORIZATION regress_ptnowner; +ALTER TABLE ptnowner1 REPLICA IDENTITY USING INDEX ptnowner1_i_key; +REPACK (CONCURRENTLY) ptnowner1; +RESET SESSION AUTHORIZATION; +ALTER TABLE ptnowner OWNER TO regress_ptnowner; +CREATE TEMP TABLE ptnowner_oldnodes AS + SELECT oid, relname, relfilenode FROM pg_partition_tree('ptnowner') AS tree + JOIN pg_class AS c ON c.oid=tree.relid; +SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a + JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; + relname | ?column? +-----------+---------- + ptnowner | t + ptnowner1 | t + ptnowner2 | t +(3 rows) + +DROP TABLE ptnowner; +DROP ROLE regress_ptnowner; diff --git a/contrib/test_decoding/meson.build b/contrib/test_decoding/meson.build index cf5b74cf1ab..ac655853d26 100644 --- a/contrib/test_decoding/meson.build +++ b/contrib/test_decoding/meson.build @@ -34,6 +34,7 @@ tests += { 'replorigin', 'time', 'messages', + 'repack', 'spill', 'slot', 'truncate', diff --git a/contrib/test_decoding/sql/repack.sql b/contrib/test_decoding/sql/repack.sql new file mode 100644 index 00000000000..bf66bb441ac --- /dev/null +++ b/contrib/test_decoding/sql/repack.sql @@ -0,0 +1,25 @@ +-- Test REPACK (CONCURRENTLY). +-- This isn't strictly about decoding, but it involves logical decoding +-- and requires to be run under higher than minimal wal_level, so we can't +-- have it in the main regression test suite. + + +-- Ownership of partitions is checked +CREATE TABLE ptnowner(i int unique not null) PARTITION BY LIST (i); +CREATE INDEX ptnowner_i_idx ON ptnowner(i); +CREATE TABLE ptnowner1 PARTITION OF ptnowner FOR VALUES IN (1); +CREATE ROLE regress_ptnowner; +CREATE TABLE ptnowner2 PARTITION OF ptnowner FOR VALUES IN (2); +ALTER TABLE ptnowner1 OWNER TO regress_ptnowner; +SET SESSION AUTHORIZATION regress_ptnowner; +ALTER TABLE ptnowner1 REPLICA IDENTITY USING INDEX ptnowner1_i_key; +REPACK (CONCURRENTLY) ptnowner1; +RESET SESSION AUTHORIZATION; +ALTER TABLE ptnowner OWNER TO regress_ptnowner; +CREATE TEMP TABLE ptnowner_oldnodes AS + SELECT oid, relname, relfilenode FROM pg_partition_tree('ptnowner') AS tree + JOIN pg_class AS c ON c.oid=tree.relid; +SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a + JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; +DROP TABLE ptnowner; +DROP ROLE regress_ptnowner; diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out index 71270134985..b767316cf6b 100644 --- a/src/test/regress/expected/cluster.out +++ b/src/test/regress/expected/cluster.out @@ -552,8 +552,6 @@ ALTER TABLE ptnowner1 OWNER TO regress_ptnowner; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; ERROR: permission denied for table ptnowner -ALTER TABLE ptnowner1 REPLICA IDENTITY USING INDEX ptnowner1_i_key; -REPACK (CONCURRENTLY) ptnowner1; RESET SESSION AUTHORIZATION; ALTER TABLE ptnowner OWNER TO regress_ptnowner; CREATE TEMP TABLE ptnowner_oldnodes AS @@ -562,30 +560,7 @@ CREATE TEMP TABLE ptnowner_oldnodes AS SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; WARNING: permission denied to execute CLUSTER on "ptnowner2", skipping it --- still can't repack without a replica identity -ALTER TABLE ptnowner1 REPLICA IDENTITY DEFAULT; -REPACK (CONCURRENTLY) ptnowner1; -ERROR: cannot process relation "ptnowner1" -HINT: Relation "ptnowner1" has no identity index. RESET SESSION AUTHORIZATION; -SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a - JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; - relname | ?column? ------------+---------- - ptnowner | t - ptnowner1 | f - ptnowner2 | t -(3 rows) - -SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a - JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; - relname | ?column? ------------+---------- - ptnowner | t - ptnowner1 | f - ptnowner2 | t -(3 rows) - DROP TABLE ptnowner; DROP ROLE regress_ptnowner; -- Test CLUSTER with external tuplesorting @@ -731,6 +706,10 @@ COMMIT; -- -- REPACK -- +-- Note we cannot test working REPACK (CONCURRENTLY) here, because the +-- tests could be run with wal_level=minimal, so those tests are +-- elsewhere. +-- ---------------------------------------------------------------------- -- REPACK handles individual tables identically to CLUSTER, but it's worth -- checking if it handles table hierarchies identically as well. diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql index 6746236ffec..a22c75282ee 100644 --- a/src/test/regress/sql/cluster.sql +++ b/src/test/regress/sql/cluster.sql @@ -262,8 +262,6 @@ CREATE TABLE ptnowner2 PARTITION OF ptnowner FOR VALUES IN (2); ALTER TABLE ptnowner1 OWNER TO regress_ptnowner; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; -ALTER TABLE ptnowner1 REPLICA IDENTITY USING INDEX ptnowner1_i_key; -REPACK (CONCURRENTLY) ptnowner1; RESET SESSION AUTHORIZATION; ALTER TABLE ptnowner OWNER TO regress_ptnowner; CREATE TEMP TABLE ptnowner_oldnodes AS @@ -271,14 +269,7 @@ CREATE TEMP TABLE ptnowner_oldnodes AS JOIN pg_class AS c ON c.oid=tree.relid; SET SESSION AUTHORIZATION regress_ptnowner; CLUSTER ptnowner USING ptnowner_i_idx; --- still can't repack without a replica identity -ALTER TABLE ptnowner1 REPLICA IDENTITY DEFAULT; -REPACK (CONCURRENTLY) ptnowner1; RESET SESSION AUTHORIZATION; -SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a - JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; -SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a - JOIN ptnowner_oldnodes b USING (oid) ORDER BY a.relname COLLATE "C"; DROP TABLE ptnowner; DROP ROLE regress_ptnowner; @@ -346,6 +337,10 @@ COMMIT; -- -- REPACK -- +-- Note we cannot test working REPACK (CONCURRENTLY) here, because the +-- tests could be run with wal_level=minimal, so those tests are +-- elsewhere. +-- ---------------------------------------------------------------------- -- REPACK handles individual tables identically to CLUSTER, but it's worth -- 2.47.3 --5vljmhsecqh6fok5--