@@ -105,55 +105,78 @@ END
105105$$ LANGUAGE PLPGSQL;
106106
107107-- Dump the invalidation log rows of the inval_log_test fixture so they
108- -- are part of the baseline/updated/restored comparison.
109- SELECT h .table_name AS hypertable,
110- l .lowest_modified_value , l .greatest_modified_value
108+ -- are part of the baseline/updated/restored comparison. The seqnum
109+ -- column only exists from 2.30; this runs on the post-update version,
110+ -- which is the same for all three databases, so the branch taken is
111+ -- identical and the outputs stay comparable.
112+ SELECT EXISTS (
113+ SELECT FROM information_schema .columns
114+ WHERE table_schema = ' _timescaledb_catalog'
115+ AND table_name = ' continuous_aggs_hypertable_invalidation_log'
116+ AND column_name = ' seqnum' ) AS has_inval_log_seqnum \gset
117+
118+ -- Collect the live rows in the same shape as inval_log_snapshot so both
119+ -- the dumps below and the verification compare like with like. This is
120+ -- the only place that has to know whether seqnum exists.
121+ CREATE TEMP VIEW inval_log_live AS
122+ SELECT ' hypertable' ::text AS log, h .table_name AS name,
123+ l .lowest_modified_value , l .greatest_modified_value ,
124+ \if :has_inval_log_seqnum
125+ l .seqnum
126+ \else
127+ NULL ::integer AS seqnum
128+ \endif
111129FROM _timescaledb_catalog .continuous_aggs_hypertable_invalidation_log l
112130JOIN _timescaledb_catalog .hypertable h ON h .id = l .hypertable_id
113131WHERE h .table_name = ' inval_log_test'
114- ORDER BY 1 , 2 , 3 ;
115-
116- SELECT ca .user_view_name AS cagg,
117- l .lowest_modified_value , l .greatest_modified_value
132+ UNION ALL
133+ SELECT ' materialization' , ca .user_view_name ,
134+ l .lowest_modified_value , l .greatest_modified_value ,
135+ \if :has_inval_log_seqnum
136+ l .seqnum
137+ \else
138+ NULL ::integer
139+ \endif
118140FROM _timescaledb_catalog .continuous_aggs_materialization_invalidation_log l
119141JOIN _timescaledb_catalog .continuous_agg ca ON ca .mat_hypertable_id = l .materialization_id
120- WHERE ca .user_view_name IN (' mat_invallog_1' , ' mat_invallog_2' )
121- ORDER BY 1 , 2 , 3 ;
142+ WHERE ca .user_view_name IN (' mat_invallog_1' , ' mat_invallog_2' );
143+
144+ SELECT name AS hypertable, lowest_modified_value, greatest_modified_value, seqnum
145+ FROM inval_log_live
146+ WHERE log = ' hypertable'
147+ ORDER BY 1 , 2 , 3 , 4 ;
148+
149+ SELECT name AS cagg, lowest_modified_value, greatest_modified_value, seqnum
150+ FROM inval_log_live
151+ WHERE log = ' materialization'
152+ ORDER BY 1 , 2 , 3 , 4 ;
122153
123154-- Verify the live invalidation logs still hold exactly the rows
124155-- snapshotted at the end of setup, i.e. an update script that rebuilds
125- -- the log catalogs neither lost nor invented rows.
156+ -- the log catalogs neither lost nor invented rows. seqnum is part of the
157+ -- comparison: EXCEPT ALL compares rows with NULL treated as equal to
158+ -- NULL, so on versions without the column both sides are NULL and only
159+ -- the other values decide, while from 2.30 on a changed seqnum shows up
160+ -- as a row that is both missing and unexpected.
126161DO $$
127162DECLARE
128163 difference TEXT ;
129164BEGIN
130- WITH live (log, name, lowest_modified_value, greatest_modified_value) AS (
131- SELECT ' hypertable' ::text , h .table_name ,
132- l .lowest_modified_value , l .greatest_modified_value
133- FROM _timescaledb_catalog .continuous_aggs_hypertable_invalidation_log l
134- JOIN _timescaledb_catalog .hypertable h ON h .id = l .hypertable_id
135- WHERE h .table_name = ' inval_log_test'
136- UNION ALL
137- SELECT ' materialization' , ca .user_view_name ,
138- l .lowest_modified_value , l .greatest_modified_value
139- FROM _timescaledb_catalog .continuous_aggs_materialization_invalidation_log l
140- JOIN _timescaledb_catalog .continuous_agg ca ON ca .mat_hypertable_id = l .materialization_id
141- WHERE ca .user_view_name IN (' mat_invallog_1' , ' mat_invallog_2' )
142- )
143- SELECT string_agg(format(' %s [%s]: (%s, %s, %s)' , src, diff .log , diff .name ,
144- diff .lowest_modified_value , diff .greatest_modified_value ), E' \n ' )
165+ SELECT string_agg(format(' %s [%s]: (%s, %s, %s, seqnum %s)' , src, diff .log , diff .name ,
166+ diff .lowest_modified_value , diff .greatest_modified_value ,
167+ coalesce(diff .seqnum ::text , ' NULL' )), E' \n ' )
145168 INTO difference
146169 FROM (
147170 SELECT ' missing after update' AS src, *
148171 FROM (SELECT * FROM inval_log_snapshot
149172 EXCEPT ALL
150- SELECT * FROM live ) missing
173+ SELECT * FROM inval_log_live ) missing
151174 UNION ALL
152175 SELECT ' unexpected after update' , *
153- FROM (SELECT * FROM live
176+ FROM (SELECT * FROM inval_log_live
154177 EXCEPT ALL
155178 SELECT * FROM inval_log_snapshot) unexpected
156- ) diff (src, log, name, lowest_modified_value, greatest_modified_value);
179+ ) diff (src, log, name, lowest_modified_value, greatest_modified_value, seqnum );
157180
158181 IF difference IS NOT NULL THEN
159182 RAISE EXCEPTION ' invalidation log content changed across the update'
0 commit comments