CREATE TABLE heaptest (a integer, b text); REVOKE ALL ON heaptest FROM PUBLIC; -- Check that invalid skip option is rejected SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'rope'); ERROR: invalid skip option HINT: Valid skip options are "all-visible", "all-frozen", and "none". -- Check specifying invalid block ranges when verifying an empty table SELECT * FROM verify_heapam(relation := 'heaptest', startblock := 0, endblock := 0); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', startblock := 5, endblock := 8); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) -- Check that valid options are not rejected nor corruption reported -- for an empty table, and that skip enum-like parameter is case-insensitive SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'all-frozen'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'all-visible'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'None'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'All-Frozen'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'All-Visible'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'NONE'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'ALL-FROZEN'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'ALL-VISIBLE'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) -- Add some data so subsequent tests are not entirely trivial INSERT INTO heaptest (a, b) (SELECT gs, repeat('x', gs) FROM generate_series(1,50) gs); -- pg_stat_io test: -- verify_heapam always uses a BAS_BULKREAD BufferAccessStrategy, whereas a -- sequential scan does so only if the table is large enough when compared to -- shared buffers (see initscan()). CREATE DATABASE ... also unconditionally -- uses a BAS_BULKREAD strategy, but we have chosen to use a tablespace and -- verify_heapam to provide coverage instead of adding another expensive -- operation to the main regression test suite. -- -- Create an alternative tablespace and move the heaptest table to it, causing -- it to be rewritten and all the blocks to reliably evicted from shared -- buffers -- guaranteeing actual reads when we next select from it in the -- same transaction. The heaptest table is smaller than the default -- wal_skip_threshold, so a wal_level=minimal commit reads the table into -- shared_buffers. A transaction delays that and excludes any autovacuum. SET allow_in_place_tablespaces = true; CREATE TABLESPACE regress_test_stats_tblspc LOCATION ''; SELECT sum(reads) AS stats_bulkreads_before FROM pg_stat_io WHERE context = 'bulkread' \gset BEGIN; ALTER TABLE heaptest SET TABLESPACE regress_test_stats_tblspc; -- Check that valid options are not rejected nor corruption reported -- for a non-empty table SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'all-frozen'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'all-visible'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', startblock := 0, endblock := 0); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) COMMIT; -- verify_heapam should have read in the page written out by -- ALTER TABLE ... SET TABLESPACE ... -- causing an additional bulkread, which should be reflected in pg_stat_io. SELECT pg_stat_force_next_flush(); pg_stat_force_next_flush -------------------------- (1 row) SELECT sum(reads) AS stats_bulkreads_after FROM pg_stat_io WHERE context = 'bulkread' \gset SELECT :stats_bulkreads_after > :stats_bulkreads_before; ?column? ---------- t (1 row) CREATE ROLE regress_heaptest_role; -- verify permissions are checked (error due to function not callable) SET ROLE regress_heaptest_role; SELECT * FROM verify_heapam(relation := 'heaptest'); ERROR: permission denied for function verify_heapam RESET ROLE; GRANT EXECUTE ON FUNCTION verify_heapam(regclass, boolean, boolean, text, bigint, bigint) TO regress_heaptest_role; -- verify permissions are now sufficient SET ROLE regress_heaptest_role; SELECT * FROM verify_heapam(relation := 'heaptest'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) RESET ROLE; -- Check specifying invalid block ranges when verifying a non-empty table. SELECT * FROM verify_heapam(relation := 'heaptest', startblock := 0, endblock := 10000); ERROR: ending block number must be between 0 and 0 SELECT * FROM verify_heapam(relation := 'heaptest', startblock := 10000, endblock := 11000); ERROR: starting block number must be between 0 and 0 -- Vacuum freeze to change the xids encountered in subsequent tests VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) heaptest; -- Check that valid options are not rejected nor corruption reported -- for a non-empty frozen table SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'none'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'all-frozen'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', skip := 'all-visible'); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) SELECT * FROM verify_heapam(relation := 'heaptest', startblock := 0, endblock := 0); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) -- Check that partitioned tables (the parent ones) which don't have visibility -- maps are rejected CREATE TABLE test_partitioned (a int, b text default repeat('x', 5000)) PARTITION BY list (a); SELECT * FROM verify_heapam('test_partitioned', startblock := NULL, endblock := NULL); ERROR: cannot check relation "test_partitioned" DETAIL: This operation is not supported for partitioned tables. -- Check that valid options are not rejected nor corruption reported -- for an empty partition table (the child one) CREATE TABLE test_partition partition OF test_partitioned FOR VALUES IN (1); SELECT * FROM verify_heapam('test_partition', startblock := NULL, endblock := NULL); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) -- Check that valid options are not rejected nor corruption reported -- for a non-empty partition table (the child one) INSERT INTO test_partitioned (a) (SELECT 1 FROM generate_series(1,1000) gs); SELECT * FROM verify_heapam('test_partition', startblock := NULL, endblock := NULL); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) -- Check that indexes are rejected CREATE INDEX test_index ON test_partition (a); SELECT * FROM verify_heapam('test_index', startblock := NULL, endblock := NULL); ERROR: cannot check relation "test_index" DETAIL: This operation is not supported for indexes. -- Check that views are rejected CREATE VIEW test_view AS SELECT 1; SELECT * FROM verify_heapam('test_view', startblock := NULL, endblock := NULL); ERROR: cannot check relation "test_view" DETAIL: This operation is not supported for views. -- Check that sequences are rejected CREATE SEQUENCE test_sequence; SELECT * FROM verify_heapam('test_sequence', startblock := NULL, endblock := NULL); blkno | offnum | attnum | msg -------+--------+--------+----- (0 rows) -- Check that foreign tables are rejected CREATE FOREIGN DATA WRAPPER dummy; CREATE SERVER dummy_server FOREIGN DATA WRAPPER dummy; CREATE FOREIGN TABLE test_foreign_table () SERVER dummy_server; SELECT * FROM verify_heapam('test_foreign_table', startblock := NULL, endblock := NULL); ERROR: cannot check relation "test_foreign_table" DETAIL: This operation is not supported for foreign tables. -- cleanup DROP TABLE heaptest; DROP TABLESPACE regress_test_stats_tblspc; DROP TABLE test_partition; DROP TABLE test_partitioned; DROP OWNED BY regress_heaptest_role; -- permissions DROP ROLE regress_heaptest_role;