-- ALTER INDEX ... SET of a sift_col option that names columns is checked against the columns of the index, as CREATE INDEX does, and a value that does -- not fit fails the ALTER and leaves the options as they were (it must never leave an index that fails the queries, inserts and VACUUM of its table). -- Every ALTER runs in a new session (\c): the first statement of a session that has not used sift yet loads the library while it runs, which used to be too -- late for the check. SET client_min_messages = warning; CREATE EXTENSION pg_sift_test CASCADE; SET sift.test_col_legacy_options = on; CREATE TABLE ao (id int, pid int, d date, ts timestamptz, cc text, f float8, metrics jsonb, parts jsonb) WITH (autovacuum_enabled = off); INSERT INTO ao SELECT i, i % 50, date '2024-01-01' + i % 300, timestamptz '2024-01-01' + i * interval '1 minute', 'c' || i % 7, i % 10, jsonb_build_object('a', i % 10), jsonb_build_array(jsonb_build_object('kind', 't' || i % 3)) FROM generate_series(1, 3000) i; CREATE INDEX ao_paths ON ao USING sift_col (id, pid, d, ts, cc, f, metrics, parts) WITH (paths = 'metrics.* float8, parts[]{kind text}'); CREATE TABLE ap (id int, pid int, d date, ts timestamptz, cc text, f float8) WITH (autovacuum_enabled = off); INSERT INTO ap SELECT i, i % 50, date '2024-01-01' + i % 300, timestamptz '2024-01-01' + i * interval '1 minute', 'c' || i % 7, i % 10 FROM generate_series(1, 3000) i; CREATE INDEX ap_plain ON ap USING sift_col (id, pid, d, ts, cc, f); -- a table with more default dimensions than the cube holds: the cells of an explicit list of calendar columns come first, the default dims give way; -- more dates than the cube holds dimensions are refused CREATE TABLE aw (c1 int, c2 int, c3 int, c4 int, c5 int, c6 int, c7 int, c8 int, c9 int, c10 int, c11 int, c12 int, c13 int, c14 int, c15 int, c16 int, d1 date, d2 date) WITH (autovacuum_enabled = off); INSERT INTO aw SELECT i, i % 3, i % 4, i % 5, i % 6, i % 7, i % 8, i % 9, i % 3, i % 4, i % 5, i % 6, i % 7, i % 8, i % 9, i % 2, date '2024-01-01' + i % 30, date '2024-01-01' + i % 20 FROM generate_series(1, 2000) i; CREATE INDEX aw_wide ON aw USING sift_col (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, d1, d2); CREATE TABLE ad (d1 date, d2 date, d3 date, d4 date, d5 date, d6 date, d7 date, d8 date, d9 date, d10 date, d11 date, d12 date, d13 date, d14 date, d15 date, d16 date, d17 date) WITH (autovacuum_enabled = off); INSERT INTO ad SELECT date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i, date '2024-01-01' + i FROM generate_series(1, 100) i; CREATE INDEX ad_dates ON ad USING sift_col (d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17) WITH (calendar_columns = 'off'); -- an index with paths takes calendar cells too (3.4; 3.3 refused them) \c ALTER INDEX ao_paths SET (calendar_columns = 'd'); \c ALTER INDEX ao_paths SET (calendar_columns = 'all'); -- a column that is not in the index, and one of a type the option does not take \c ALTER INDEX ao_paths SET (key_columns = 'nope'); ERROR: invalid key_columns option: unknown column \c ALTER INDEX ao_paths SET (key_columns = 'f'); ERROR: invalid key_columns option: not a plain integer, text or uuid column \c ALTER INDEX ao_paths SET (key_columns = 'auto: nope'); ERROR: invalid key_columns option: unknown column \c ALTER INDEX ao_paths SET (rollup_columns = 'nope, pid'); ERROR: invalid rollup_columns option: "nope" is not a column of the index \c ALTER INDEX ao_paths SET (rollup_columns = 'f, pid'); ERROR: invalid rollup_columns option: "f" must be a boolean, integer, date, numeric or text column \c SET sift.test_col_legacy_options = on; ALTER INDEX ao_paths SET (order_columns = 'nope'); ERROR: invalid order_columns option: unknown column \c SET sift.test_col_legacy_options = on; ALTER INDEX ao_paths SET (order_columns = 'cc'); ERROR: invalid order_columns option: not an integer, date, timestamp, numeric or float column \c ALTER INDEX ao_paths SET (return_columns = 'nope'); ERROR: invalid return_columns option: unknown column \c ALTER INDEX ao_paths SET (return_columns = 'pid'); ERROR: invalid return_columns option: not a text, varchar or uuid column \c ALTER INDEX ap_plain SET (calendar_columns = 'id'); ERROR: invalid calendar_columns option: "id" must be a date, timestamp or timestamptz column \c ALTER INDEX ap_plain SET (calendar_columns = 'nope'); ERROR: invalid calendar_columns option: "nope" is not a column of the index \c ALTER INDEX ap_plain SET (calendar_columns = 'd, d'); ERROR: invalid calendar_columns option: "d" is named twice \c ALTER INDEX aw_wide SET (calendar_columns = 'd1, d2'); \c ALTER INDEX ad_dates SET (calendar_columns = 'd1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17'); ERROR: invalid calendar_columns option: too many dimensions -- the refused options changed nothing (aw_wide took its list), and the table still takes statements \c SELECT relname, reloptions FROM pg_class WHERE relname IN ('ao_paths', 'ap_plain', 'aw_wide', 'ad_dates') ORDER BY 1; relname | reloptions ----------+--------------------------------------------------------------------- ad_dates | {calendar_columns=off} ao_paths | {"paths=metrics.* float8, parts[]{kind text}",calendar_columns=all} ap_plain | aw_wide | {"rollup_columns=auto: c2, c9","calendar_columns=d1, d2"} (4 rows) SET client_min_messages = warning; INSERT INTO ao VALUES (0, 0, '2024-01-01', now(), 'x', 0, '{"a": 1}', '[]'); SET sift.enable_agg = on; SELECT count(*) FROM ao; count ------- 3001 (1 row) VACUUM ao; -- values that fit are applied, and the table goes on working \c ALTER INDEX ao_paths SET (key_columns = 'pid', order_columns = 'pid', rollup_columns = 'pid, d', return_columns = 'cc'); \c ALTER INDEX ap_plain SET (calendar_columns = 'd, ts'); SET client_min_messages = warning; INSERT INTO ao VALUES (-1, 0, '2024-01-01', now(), 'x', 0, '{"a": 1}', '[]'); INSERT INTO ap VALUES (-1, 0, '2024-01-01', now(), 'x', 0); SELECT count(*) FROM ao; count ------- 3002 (1 row) SELECT count(*) FROM ap; count ------- 3001 (1 row) -- auto is the word of the default for calendar_columns and rollup (empty, and 'default' for rollup, mean the same); a word that is none of them is refused \c ALTER INDEX ap_plain SET (calendar_columns = 'auto', rollup_leaves = 'auto'); ALTER INDEX ap_plain SET (rollup_leaves = 'default'); \c ALTER INDEX ap_plain SET (rollup_leaves = 'nope'); ERROR: invalid rollup_leaves option: "nope" is not a leaf declared in paths ALTER INDEX ap_plain SET (calendar_columns = 'autos'); ERROR: invalid calendar_columns option: "autos" is not a column of the index ALTER INDEX ap_plain RESET (calendar_columns, rollup); VACUUM ao; VACUUM ap; SELECT sift.col_verify('ao_paths', true), sift.col_verify('ap_plain', true); col_verify | col_verify ------------+------------ | (1 row) DROP TABLE ao, ap, aw, ad; DROP EXTENSION pg_sift_test, pg_sift CASCADE;