-- Column format minor 4 beside minor 3: an index reads the segments of both, whatever sift.col_format_minor is -- when they are written, and a merge or a VACUUM rewrite writes the setting's minor. fmt lists the minors of the segments, oldest first. CREATE EXTENSION pg_sift; CREATE EXTENSION pg_sift_test; SET client_min_messages = warning; CREATE FUNCTION fmt(idx regclass) RETURNS text LANGUAGE sql AS $$ SELECT string_agg(format::text, ',' ORDER BY gen) FROM sift.col_segments(idx) WHERE kind = 'immutable' $$; CREATE FUNCTION same(q text) RETURNS bool LANGUAGE plpgsql AS $$ DECLARE a text; b text; BEGIN SET LOCAL sift.enable_agg = on; EXECUTE format('SELECT string_agg(x::text, E''\n'' ORDER BY x::text) FROM (%s) x', q) INTO a; SET LOCAL sift.enable_agg = off; EXECUTE format('SELECT string_agg(x::text, E''\n'' ORDER BY x::text) FROM (%s) x', q) INTO b; RETURN a IS NOT DISTINCT FROM b; END $$; SHOW sift.col_format_minor; sift.col_format_minor ----------------------- 15 (1 row) SET sift.col_format_minor = 2; ERROR: 2 is outside the valid range for parameter "sift.col_format_minor" (3 .. 15) SET sift.col_format_minor = 5; ERROR: invalid value for parameter "sift.col_format_minor": 5 DETAIL: Column format minor 5 is written for wide leaves only, whatever the setting. HINT: Use 3 (pg_sift 3.0), 4 (pg_sift 3.1), 6, 7, 8, 9, 10, 12, 13, 14 or 15. CREATE TABLE f (id int, grp int, v numeric(10,2)); INSERT INTO f SELECT g, g % 9, g % 1000 / 8.0 FROM generate_series(1, 30000) g; SET sift.col_format_minor = 3; CREATE INDEX f_col ON f USING sift_col (id, grp, v) WITH (cube_minmax = false, superunit = 0); SELECT fmt('f_col'); fmt ----- 3 (1 row) RESET sift.col_format_minor; INSERT INTO f SELECT g, g % 9, g % 1000 / 8.0 FROM generate_series(30001, 60000) g; SELECT sift.col_promote('f_col'); col_promote ------------- 1 (1 row) SELECT fmt('f_col'); fmt ----- 3,4 (1 row) SELECT same('SELECT grp, count(*), sum(v), avg(v) FROM f GROUP BY grp') AS mixed_agg, same('SELECT count(*), sum(v) FROM f WHERE id BETWEEN 25000 AND 35000') AS mixed_filter; mixed_agg | mixed_filter -----------+-------------- t | t (1 row) SELECT sift.col_verify('f_col', true); col_verify ------------ (1 row) -- the merge of both writes the setting's minor SELECT sift.col_merge('f_col', true); col_merge ----------- 1 (1 row) SELECT fmt('f_col'); fmt ----- 4 (1 row) SELECT same('SELECT grp, count(*), sum(v) FROM f GROUP BY grp') AS merged_agg; merged_agg ------------ t (1 row) SELECT sift.col_verify('f_col', true); col_verify ------------ (1 row) -- 3.0 compatibility: a merge under minor 3 writes minor 3 again SET sift.col_format_minor = 3; INSERT INTO f SELECT g, g % 9, 1 FROM generate_series(60001, 90000) g; SELECT sift.col_promote('f_col'); col_promote ------------- 1 (1 row) SELECT sift.col_merge('f_col', true); col_merge ----------- 1 (1 row) SELECT fmt('f_col'); fmt ----- 3 (1 row) SELECT sift.col_verify('f_col', true); col_verify ------------ (1 row) RESET sift.col_format_minor; -- REINDEX writes minor 4 REINDEX INDEX f_col; SELECT fmt('f_col'); fmt ----- 4 (1 row) SELECT same('SELECT grp, count(*), sum(v) FROM f GROUP BY grp') AS reindexed_agg; reindexed_agg --------------- t (1 row) -- the same column on the other views: the test hook agrees, the write buffer has none, a sift_table lists it too SELECT (SELECT string_agg(format::text, ',' ORDER BY gen) FROM sift._test_col_formats('f_col')) = fmt('f_col') AS hook_agrees; hook_agrees ------------- t (1 row) INSERT INTO f SELECT g, g % 9, 1 FROM generate_series(90001, 90010) g; SELECT kind, format FROM sift.col_segments('f_col') WHERE kind <> 'immutable'; kind | format --------+-------- buffer | (1 row) SELECT preagg_bytes > 0 AS has_sidecar FROM sift.col_segments('f_col') WHERE kind = 'immutable'; has_sidecar ------------- t (1 row) CREATE TABLE ft (id int, grp int) USING sift_table; SET sift.col_format_minor = 3; INSERT INTO ft SELECT g, g % 9 FROM generate_series(1, 20000) g; VACUUM ft; RESET sift.col_format_minor; INSERT INTO ft SELECT g, g % 9 FROM generate_series(20001, 40000) g; VACUUM ft; SELECT kind, format, count(*) FROM sift.table_segments('ft') GROUP BY 1, 2 ORDER BY 1, 2; kind | format | count ------------+--------+------- buffer | | 1 columns | 3 | 1 columns | 7 | 1 tombstones | | 1 (4 rows) DROP TABLE f, ft; DROP FUNCTION fmt(regclass), same(text); DROP EXTENSION pg_sift_test; DROP EXTENSION pg_sift;