# REPACK (CONCURRENTLY) with multiple snapshots: rows that land in blocks # beyond the scan's rs_nblocks while a range boundary is being processed. setup { CREATE EXTENSION injection_points; CREATE TABLE t(i int PRIMARY KEY, j text) WITH (fillfactor = 100); -- about 4 full pages INSERT INTO t SELECT x, repeat('x', 200) FROM generate_series(1, 140) x; CREATE TABLE expected(i int, j text); } teardown { DROP TABLE t; DROP TABLE expected; DROP EXTENSION injection_points; } session s1 setup { SET repack_snapshot_after = 2; SELECT injection_points_set_local(); SELECT injection_points_attach('repack-concurrently-new-range', 'wait'); } step blocks { SELECT pg_relation_size('t') / 8192 AS nblocks; } step repack { REPACK (CONCURRENTLY) t; } step check { SELECT count(*) AS missing FROM expected e LEFT JOIN t USING (i) WHERE t.i IS NULL; SELECT (SELECT count(*) FROM t) AS rows_after, (SELECT count(*) FROM expected) AS rows_expected; } session s2 # While REPACK waits at the first range boundary, insert rows. The table is # full, so they go into new blocks, i.e. beyond the block count the scan saw. step extend { INSERT INTO t SELECT x, repeat('y', 200) FROM generate_series(1001, 1100) x; SELECT min(tid_block(ctid)), max(tid_block(ctid)) FROM t WHERE i > 1000; INSERT INTO expected SELECT * FROM t; } step wakeup { SELECT injection_points_detach('repack-concurrently-new-range'); SELECT injection_points_wakeup('repack-concurrently-new-range'); } permutation blocks repack extend wakeup check