# Blocks with no tuples at scan time are skipped without finalizing a range. # Rows inserted there after the scan passed them are dropped by the next # finalize_block_range() (which uses the old range end) and never copied. setup { CREATE EXTENSION injection_points; CREATE TABLE t(i int PRIMARY KEY, j text) WITH (fillfactor = 100, autovacuum_enabled = off); INSERT INTO t SELECT x, repeat('x', 200) FROM generate_series(1, 200) 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 repack { REPACK (CONCURRENTLY) t; } step check { SELECT count(*) AS missing FROM expected e LEFT JOIN t USING (i) WHERE t.i IS NULL; } session s2 # Empty blocks 2 and 3 completely, keep 0, 1, 4, 5. step empty { DELETE FROM t WHERE tid_block(ctid) IN (2, 3); SELECT tid_block(ctid) AS blk, count(*) FROM t GROUP BY 1 ORDER BY 1; } step vac { VACUUM t; } # REPACK is now at the first tuple of block 4, blocks 2-3 already passed. step fill_gap { INSERT INTO t SELECT x, repeat('y', 200) FROM generate_series(1001, 1040) x; SELECT tid_block(ctid) AS blk, count(*) FROM t WHERE i > 1000 GROUP BY 1 ORDER BY 1; 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 empty vac repack fill_gap wakeup check