1-- This file and its contents are licensed under the Timescale License.
2-- Please see the included NOTICE for copyright information and
3-- LICENSE-TIMESCALE for a copy of the license.
4
5-- test add and remove refresh policy apis
6
7SET ROLE :ROLE_DEFAULT_PERM_USER;
8
9
10--TEST1 ---
11--basic test with count
12CREATE TABLE int_tab (a integer, b integer, c integer);
13SELECT table_name FROM create_hypertable('int_tab', 'a', chunk_time_interval=> 10);
14
15INSERT INTO int_tab VALUES( 3 , 16 , 20);
16INSERT INTO int_tab VALUES( 1 , 10 , 20);
17INSERT INTO int_tab VALUES( 1 , 11 , 20);
18INSERT INTO int_tab VALUES( 1 , 12 , 20);
19INSERT INTO int_tab VALUES( 1 , 13 , 20);
20INSERT INTO int_tab VALUES( 1 , 14 , 20);
21INSERT INTO int_tab VALUES( 2 , 14 , 20);
22INSERT INTO int_tab VALUES( 2 , 15 , 20);
23INSERT INTO int_tab VALUES( 2 , 16 , 20);
24
25CREATE OR REPLACE FUNCTION integer_now_int_tab() returns int LANGUAGE SQL STABLE as $$ SELECT coalesce(max(a), 0) FROM int_tab $$;
26SELECT set_integer_now_func('int_tab', 'integer_now_int_tab');
27
28
29CREATE MATERIALIZED VIEW mat_m1( a, countb )
30WITH (timescaledb.continuous, timescaledb.materialized_only=true)
31as
32SELECT a, count(b)
33FROM int_tab
34GROUP BY time_bucket(1, a), a WITH NO DATA;
35
36\c :TEST_DBNAME :ROLE_SUPERUSER
37DELETE FROM _timescaledb_config.bgw_job WHERE TRUE;
38
39SET ROLE :ROLE_DEFAULT_PERM_USER;
40SELECT count(*) FROM _timescaledb_config.bgw_job;
41
42\set ON_ERROR_STOP 0
43\set VERBOSITY default
44SELECT add_continuous_aggregate_policy('int_tab', '1 day'::interval, 10 , '1 h'::interval);
45SELECT add_continuous_aggregate_policy('mat_m1', '1 day'::interval, 10 , '1 h'::interval);
46SELECT add_continuous_aggregate_policy('mat_m1', '1 day'::interval, 10 );
47SELECT add_continuous_aggregate_policy('mat_m1', 10, '1 day'::interval, '1 h'::interval);
48--start_interval < end_interval
49SELECT add_continuous_aggregate_policy('mat_m1', 5, 10, '1h'::interval);
50--refresh window less than two buckets
51SELECT add_continuous_aggregate_policy('mat_m1', 11, 10, '1h'::interval);
52SELECT add_continuous_aggregate_policy('mat_m1', 20, 10, '1h'::interval) as job_id \gset
53
54--adding again should warn/error
55SELECT add_continuous_aggregate_policy('mat_m1', 20, 10, '1h'::interval, if_not_exists=>false);
56SELECT add_continuous_aggregate_policy('mat_m1', 20, 15, '1h'::interval, if_not_exists=>true);
57SELECT add_continuous_aggregate_policy('mat_m1', 20, 10, '1h'::interval, if_not_exists=>true);
58
59-- modify config and try to add, should error out
60SELECT config FROM _timescaledb_config.bgw_job where id = :job_id;
61SELECT hypertable_id as mat_id FROM _timescaledb_config.bgw_job where id = :job_id \gset
62\set VERBOSITY terse
63\set ON_ERROR_STOP 1
64
65\c :TEST_DBNAME :ROLE_SUPERUSER
66UPDATE _timescaledb_config.bgw_job
67SET config = jsonb_build_object('mat_hypertable_id', :mat_id)
68WHERE id = :job_id;
69SET ROLE :ROLE_DEFAULT_PERM_USER;
70SELECT config FROM _timescaledb_config.bgw_job where id = :job_id;
71
72\set ON_ERROR_STOP 0
73\set VERBOSITY default
74SELECT add_continuous_aggregate_policy('mat_m1', 20, 10, '1h'::interval, if_not_exists=>true);
75
76SELECT remove_continuous_aggregate_policy('int_tab');
77SELECT remove_continuous_aggregate_policy('mat_m1');
78--this one will fail
79SELECT remove_continuous_aggregate_policy('mat_m1');
80SELECT remove_continuous_aggregate_policy('mat_m1', if_not_exists=>true);
81
82--now try to add a policy as a different user than the one that created the cagg
83--should fail
84SET ROLE :ROLE_DEFAULT_PERM_USER_2;
85SELECT add_continuous_aggregate_policy('mat_m1', 20, 10, '1h'::interval) as job_id ;
86\set VERBOSITY terse
87\set ON_ERROR_STOP 1
88
89SET ROLE :ROLE_DEFAULT_PERM_USER;
90DROP MATERIALIZED VIEW mat_m1;
91
92--- code coverage tests : add policy for timestamp and date based table ---
93CREATE TABLE continuous_agg_max_mat_date(time DATE);
94SELECT create_hypertable('continuous_agg_max_mat_date', 'time');
95CREATE MATERIALIZED VIEW max_mat_view_date
96	WITH (timescaledb.continuous, timescaledb.materialized_only=true)
97	AS SELECT time_bucket('7 days', time)
98		FROM continuous_agg_max_mat_date
99		GROUP BY 1 WITH NO DATA;
100
101\set ON_ERROR_STOP 0
102\set VERBOSITY default
103SELECT add_continuous_aggregate_policy('max_mat_view_date', '2 days', 10, '1 day'::interval);
104--start_interval < end_interval
105SELECT add_continuous_aggregate_policy('max_mat_view_date', '1 day'::interval, '2 days'::interval , '1 day'::interval) ;
106--interval less than two buckets
107SELECT add_continuous_aggregate_policy('max_mat_view_date', '7 days', '1 day', '1 day'::interval);
108SELECT add_continuous_aggregate_policy('max_mat_view_date', '14 days', '1 day', '1 day'::interval);
109SELECT add_continuous_aggregate_policy('max_mat_view_date', '13 days', '-10 hours', '1 day'::interval);
110\set VERBOSITY terse
111\set ON_ERROR_STOP 1
112
113-- Negative start offset gives two bucket window:
114SELECT add_continuous_aggregate_policy('max_mat_view_date', '13 days', '-1 day', '1 day'::interval);
115SELECT remove_continuous_aggregate_policy('max_mat_view_date');
116-- Both offsets NULL:
117SELECT add_continuous_aggregate_policy('max_mat_view_date', NULL, NULL, '1 day'::interval);
118SELECT remove_continuous_aggregate_policy('max_mat_view_date');
119
120SELECT add_continuous_aggregate_policy('max_mat_view_date', '15 days', '1 day', '1 day'::interval) as job_id \gset
121SELECT config FROM _timescaledb_config.bgw_job
122WHERE id = :job_id;
123
124INSERT INTO continuous_agg_max_mat_date
125	SELECT generate_series('2019-09-01'::date, '2019-09-10'::date, '1 day');
126--- to prevent NOTICES set message level to warning
127SET client_min_messages TO warning;
128CALL run_job(:job_id);
129RESET client_min_messages;
130DROP MATERIALIZED VIEW max_mat_view_date;
131
132CREATE TABLE continuous_agg_timestamp(time TIMESTAMP);
133SELECT create_hypertable('continuous_agg_timestamp', 'time');
134
135CREATE MATERIALIZED VIEW max_mat_view_timestamp
136	WITH (timescaledb.continuous, timescaledb.materialized_only=true)
137	AS SELECT time_bucket('7 days', time)
138		FROM continuous_agg_timestamp
139		GROUP BY 1 WITH NO DATA;
140
141--the start offset overflows the smallest time value, but is capped at
142--the min value
143SELECT add_continuous_aggregate_policy('max_mat_view_timestamp', '1000000 years', '1 day' , '1 h'::interval);
144SELECT remove_continuous_aggregate_policy('max_mat_view_timestamp');
145
146\set ON_ERROR_STOP 0
147\set VERBOSITY default
148--start and end offset capped at the lowest time value, which means
149--zero size window
150SELECT add_continuous_aggregate_policy('max_mat_view_timestamp', '1000000 years', '900000 years' , '1 h'::interval);
151SELECT add_continuous_aggregate_policy('max_mat_view_timestamp', '301 days', '10 months' , '1 h'::interval);
152\set VERBOSITY terse
153\set ON_ERROR_STOP 1
154
155SELECT add_continuous_aggregate_policy('max_mat_view_timestamp', '15 days', '1 h'::interval , '1 h'::interval) as job_id \gset
156
157--- to prevent NOTICES set message level to warning
158SET client_min_messages TO warning;
159CALL run_job(:job_id);
160RESET client_min_messages ;
161
162SELECT config FROM _timescaledb_config.bgw_job
163WHERE id = :job_id;
164
165\c :TEST_DBNAME :ROLE_SUPERUSER
166UPDATE _timescaledb_config.bgw_job
167SET config = jsonb_build_object('mat_hypertable_id', :mat_id)
168WHERE id = :job_id;
169
170SET ROLE :ROLE_DEFAULT_PERM_USER;
171SELECT config FROM _timescaledb_config.bgw_job where id = :job_id;
172\set ON_ERROR_STOP 0
173SELECT add_continuous_aggregate_policy('max_mat_view_timestamp', '15 day', '1 day', '1h'::interval, if_not_exists=>true);
174SELECT add_continuous_aggregate_policy('max_mat_view_timestamp', 'xyz', '1 day', '1h'::interval, if_not_exists=>true);
175\set ON_ERROR_STOP 1
176
177DROP MATERIALIZED VIEW max_mat_view_timestamp;
178
179--smallint table
180CREATE TABLE smallint_tab (a smallint);
181SELECT table_name FROM create_hypertable('smallint_tab', 'a', chunk_time_interval=> 10);
182CREATE OR REPLACE FUNCTION integer_now_smallint_tab() returns smallint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(a)::smallint, 0::smallint) FROM smallint_tab ; $$;
183SELECT set_integer_now_func('smallint_tab', 'integer_now_smallint_tab');
184
185CREATE MATERIALIZED VIEW mat_smallint( a, countb )
186WITH (timescaledb.continuous, timescaledb.materialized_only=true)
187as
188SELECT time_bucket( SMALLINT '1', a) , count(*)
189FROM smallint_tab
190GROUP BY 1 WITH NO DATA;
191\set ON_ERROR_STOP 0
192\set VERBOSITY default
193SELECT add_continuous_aggregate_policy('mat_smallint', 15, 0 , '1 h'::interval);
194SELECT add_continuous_aggregate_policy('mat_smallint', 98898::smallint , 0::smallint, '1 h'::interval);
195SELECT add_continuous_aggregate_policy('mat_smallint', 5::smallint, 10::smallint , '1 h'::interval) as job_id \gset
196\set VERBOSITY terse
197\set ON_ERROR_STOP 1
198SELECT add_continuous_aggregate_policy('mat_smallint', 15::smallint, 0::smallint , '1 h'::interval) as job_id \gset
199INSERT INTO smallint_tab VALUES(5);
200INSERT INTO smallint_tab VALUES(10);
201INSERT INTO smallint_tab VALUES(20);
202CALL run_job(:job_id);
203SELECT * FROM mat_smallint ORDER BY 1;
204
205--remove all the data--
206TRUNCATE table smallint_tab;
207CALL refresh_continuous_aggregate('mat_smallint', NULL, NULL);
208SELECT * FROM mat_smallint ORDER BY 1;
209
210-- Case 1: overflow by subtracting from PG_INT16_MIN
211--overflow start_interval, end_interval [-32768, -32768)
212SELECT remove_continuous_aggregate_policy('mat_smallint');
213INSERT INTO smallint_tab VALUES( -32768 );
214SELECT integer_now_smallint_tab();
215SELECT add_continuous_aggregate_policy('mat_smallint', 10::smallint, 5::smallint , '1 h'::interval) as job_id \gset
216
217\set ON_ERROR_STOP 0
218CALL run_job(:job_id);
219\set ON_ERROR_STOP 1
220SELECT * FROM mat_smallint ORDER BY 1;
221
222-- overflow start_interval. now this runs as range is capped [-32768, -32765)
223INSERT INTO smallint_tab VALUES( -32760 );
224SELECT maxval, maxval - 10, maxval -5 FROM integer_now_smallint_tab() as maxval;
225CALL run_job(:job_id);
226SELECT * FROM mat_smallint ORDER BY 1;
227
228--remove all the data--
229TRUNCATE table smallint_tab;
230CALL refresh_continuous_aggregate('mat_smallint', NULL, NULL);
231SELECT * FROM mat_smallint ORDER BY 1;
232
233-- Case 2: overflow by subtracting from PG_INT16_MAX
234--overflow start and end . will fail as range is [32767, 32767]
235SELECT remove_continuous_aggregate_policy('mat_smallint');
236INSERT INTO smallint_tab VALUES( 32766 );
237INSERT INTO smallint_tab VALUES( 32767 );
238SELECT maxval, maxval - (-1), maxval - (-2) FROM integer_now_smallint_tab() as maxval;
239SELECT add_continuous_aggregate_policy('mat_smallint', -1::smallint, -3::smallint , '1 h'::interval) as job_id \gset
240\set ON_ERROR_STOP 0
241CALL run_job(:job_id);
242\set ON_ERROR_STOP 1
243SELECT * FROM mat_smallint ORDER BY 1;
244
245SELECT remove_continuous_aggregate_policy('mat_smallint');
246--overflow end . will work range is [32765, 32767)
247SELECT maxval, maxval - (1), maxval - (-2) FROM integer_now_smallint_tab() as maxval;
248SELECT add_continuous_aggregate_policy('mat_smallint', 1::smallint, -3::smallint , '1 h'::interval) as job_id \gset
249\set ON_ERROR_STOP 0
250CALL run_job(:job_id);
251SELECT * FROM mat_smallint ORDER BY 1;
252
253-- tests for interval argument conversions
254--
255\set ON_ERROR_STOP 0
256SELECT add_continuous_aggregate_policy('mat_smallint', 15, 10, '1h'::interval, if_not_exists=>true);
257SELECT add_continuous_aggregate_policy('mat_smallint', '15', 10, '1h'::interval, if_not_exists=>true);
258SELECT add_continuous_aggregate_policy('mat_smallint', '15', '10', '1h'::interval, if_not_exists=>true);
259\set ON_ERROR_STOP 1
260
261DROP MATERIALIZED VIEW mat_smallint;
262DROP TABLE smallint_tab CASCADE;
263
264--bigint table
265CREATE TABLE bigint_tab (a bigint);
266SELECT table_name FROM create_hypertable('bigint_tab', 'a', chunk_time_interval=> 10);
267CREATE OR REPLACE FUNCTION integer_now_bigint_tab() returns bigint LANGUAGE SQL STABLE as $$ SELECT 20::bigint $$;
268SELECT set_integer_now_func('bigint_tab', 'integer_now_bigint_tab');
269
270CREATE MATERIALIZED VIEW mat_bigint( a, countb )
271WITH (timescaledb.continuous, timescaledb.materialized_only=true)
272as
273SELECT time_bucket( BIGINT '1', a) , count(*)
274FROM bigint_tab
275GROUP BY 1 WITH NO DATA;
276\set ON_ERROR_STOP 0
277SELECT add_continuous_aggregate_policy('mat_bigint', 5::bigint, 10::bigint , '1 h'::interval) ;
278\set ON_ERROR_STOP 1
279SELECT add_continuous_aggregate_policy('mat_bigint', 15::bigint, 0::bigint , '1 h'::interval) as job_mid \gset
280INSERT INTO bigint_tab VALUES(5);
281INSERT INTO bigint_tab VALUES(10);
282INSERT INTO bigint_tab VALUES(20);
283CALL run_job(:job_mid);
284SELECT * FROM mat_bigint;
285
286-- test NULL for end
287SELECT remove_continuous_aggregate_policy('mat_bigint');
288SELECT add_continuous_aggregate_policy('mat_bigint', 1::smallint, NULL , '1 h'::interval) as job_id \gset
289INSERT INTO bigint_tab VALUES(500);
290CALL run_job(:job_id);
291SELECT * FROM mat_bigint WHERE a>100 ORDER BY 1;
292
293-- end of coverage tests
294