Subject: [PATCH] Add test for REPACK CONCURRENTLY with concurrent modifications --- Index: contrib/amcheck/t/007_repack_concurrently_mvcc.pl IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/contrib/amcheck/t/007_repack_concurrently_mvcc.pl b/contrib/amcheck/t/007_repack_concurrently_mvcc.pl new file mode 100644 --- /dev/null (date 1756650098221) +++ b/contrib/amcheck/t/007_repack_concurrently_mvcc.pl (date 1756650098221) @@ -0,0 +1,94 @@ + +# Copyright (c) 2021-2025, PostgreSQL Global Development Group + +# Test REPACK CONCURRENTLY with concurrent modifications +use strict; +use warnings FATAL => 'all'; + +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; + +use Test::More; + +my $node; + +# +# Test set-up +# +$node = PostgreSQL::Test::Cluster->new('CIC_test'); +$node->init; +$node->append_conf('postgresql.conf', + 'lock_timeout = ' . (1000 * $PostgreSQL::Test::Utils::timeout_default)); +$node->append_conf('postgresql.conf', 'autovacuum=off'); +$node->append_conf( + 'postgresql.conf', qq( +wal_level = logical +)); +$node->start; +$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); +$node->safe_psql('postgres', q(CREATE TABLE tbl1(i int PRIMARY KEY, j int))); +$node->safe_psql('postgres', q(CREATE TABLE tbl2(i int PRIMARY KEY, j int))); + + +# Insert 100 rows into tbl1 +$node->safe_psql('postgres', q( + INSERT INTO tbl1 SELECT i, i % 100 FROM generate_series(1,100) i +)); + +# Insert 100 rows into tbl2 +$node->safe_psql('postgres', q( + INSERT INTO tbl2 SELECT i, i % 100 FROM generate_series(1,100) i +)); + + +# Insert 100 rows into tbl1 +$node->safe_psql('postgres', q( + CREATE OR REPLACE FUNCTION log_raise(i int, j1 int, j2 int) RETURNS VOID AS $$ + BEGIN + RAISE NOTICE 'ERROR i=% j1=% j2=%', i, j1, j2; + END;$$ LANGUAGE plpgsql; +)); + +$node->safe_psql('postgres', q(CREATE UNLOGGED SEQUENCE in_row_repack START 1 INCREMENT 1;)); +$node->safe_psql('postgres', q(SELECT nextval('in_row_repack');)); + + +$node->pgbench( +'--no-vacuum --client=10 --jobs=4 --exit-on-abort --transactions=25000', +0, +[qr{actually processed}], +[qr{^$}], +'concurrent operations with REPACK CONCURRENTLY', +{ + 'concurrent_ops' => q( + SELECT pg_try_advisory_lock(42)::integer AS gotlock \gset + \if :gotlock + SELECT nextval('in_row_repack') AS last_value \gset + \if :last_value = 2 + REPACK (CONCURRENTLY) tbl2 USING INDEX tbl2_pkey; + \sleep 10 ms + \endif + SELECT pg_advisory_unlock(42); + \else + \set num random(1, 100) + BEGIN; + UPDATE tbl1 SET j = j + 1 WHERE i = :num; + UPDATE tbl2 SET j = j + 1 WHERE i = :num; + COMMIT; + SELECT setval('in_row_repack', 1); + + SELECT COUNT(*) AS suspect FROM (SELECT * FROM tbl1 LEFT OUTER JOIN tbl2 ON tbl1.i = tbl2.i WHERE tbl1.j != tbl2.j) as X \gset p_ + \if :p_suspect != 0 + SELECT pg_advisory_lock(42); -- make sure we have not any concurrent repack + SELECT COUNT(*) AS fatal FROM (SELECT log_raise(tbl1.i, tbl1.j, tbl2.j) FROM tbl1 LEFT OUTER JOIN tbl2 ON tbl1.i = tbl2.i WHERE tbl1.j != tbl2.j) as X \gset p_ + \if :p_fatal != 0 + SELECT :p_fatal / 0; + \endif + SELECT pg_advisory_unlock(42); + \endif + \endif + ) +}); + +$node->stop; +done_testing(); Index: contrib/amcheck/meson.build IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build --- a/contrib/amcheck/meson.build (revision 911e274d320364685721d5d84d8013f2f510e5aa) +++ b/contrib/amcheck/meson.build (date 1756649361369) @@ -50,6 +50,7 @@ 't/004_verify_nbtree_unique.pl', 't/005_pitr.pl', 't/006_verify_gin.pl', + 't/007_repack_concurrently_mvcc.pl', ], }, }