-- sift.col_verify's heap check must not use the index's cached state across tuples: a session that updates the index's statistics (VACUUM, ANALYZE) -- sends an invalidation that reloads the index's relcache entry and frees that state. sift.test_col_verify_inval does it at every tuple, and -- first overwrites the cached state, so a check that kept it reads garbage. CREATE EXTENSION pg_sift_test CASCADE; NOTICE: installing required extension "pg_sift" CREATE TABLE cv (id int PRIMARY KEY, g int, v float8, t text); INSERT INTO cv SELECT i, i % 7, i / 3.0, 'row ' || i FROM generate_series(1, 2000) i; CREATE INDEX cv_col ON cv USING sift_col (id, g, v, t); NOTICE: sift_col index "cv_col": 1 automatic choice (track_changes) DETAIL: track_changes = id HINT: Reasons, costs and how to turn each off: SELECT * FROM sift.index_choices('cv_col'); SELECT sift.col_verify('cv_col', true); col_verify ------------ (1 row) SET sift.test_col_verify_inval = on; SELECT sift.col_verify('cv_col', true); col_verify ------------ (1 row) SELECT sift.col_verify('cv_col', true); col_verify ------------ (1 row) RESET sift.test_col_verify_inval; SELECT sift.col_verify('cv_col', true); col_verify ------------ (1 row) DROP TABLE cv; -- A toasted value is read through the lock of the toast table, which processes the invalidation messages: the entry is reloaded in the middle of a -- tuple. A server built with assertions can do it at every such point (debug_discard_caches); the others skip the setting. SELECT coalesce((SELECT max_val::int > 0 FROM pg_settings WHERE name = 'debug_discard_caches'), false) AS discard \gset CREATE TABLE cvt (id int, t text); INSERT INTO cvt SELECT i, (SELECT string_agg(md5(i::text || j), ' ') FROM generate_series(1, 200) j) FROM generate_series(1, 30) i; SELECT count(*) AS toasted FROM cvt WHERE pg_column_toast_chunk_id(t) IS NOT NULL; toasted --------- 30 (1 row) CREATE INDEX cvt_col ON cvt USING sift_col (id, t); NOTICE: sift_col index "cvt_col": 1 advice (track_changes) DETAIL: advice: track_changes = the table has no one-column primary key HINT: Reasons, costs and how to turn each off: SELECT * FROM sift.index_choices('cvt_col'); \if :discard SET debug_discard_caches = 1; \endif SELECT sift.col_verify('cvt_col', true); col_verify ------------ (1 row) \if :discard RESET debug_discard_caches; \endif DROP TABLE cvt; DROP EXTENSION pg_sift_test, pg_sift;