timescaledb/tsl/test/sql/continuous_aggs_materialize.sql
Stephen Polcyn b57d2ac388 Cleanup TODOs and FIXMEs
Unless otherwise listed, the TODO was converted to a comment or put
into an issue tracker.

test/sql/
- triggers.sql: Made required change

tsl/test/
- CMakeLists.txt: TODO complete
- bgw_policy.sql: TODO complete
- continuous_aggs_materialize.sql: TODO complete
- compression.sql: TODO complete
- compression_algos.sql: TODO complete

tsl/src/
- compression/compression.c:
  - row_compressor_decompress_row: Expected complete
- compression/dictionary.c: FIXME complete
- materialize.c: TODO complete
- reorder.c: TODO complete
- simple8b_rle.h:
  - compressor_finish: Removed (obsolete)

src/
- extension.c: Removed due to age
- adts/simplehash.h: TODOs are from copied Postgres code
- adts/vec.h: TODO is non-significant
- planner.c: Removed
- process_utility.c
  - process_altertable_end_subcmd: Removed (PG will handle case)
2020-05-18 20:16:03 -04:00

752 lines
31 KiB
PL/PgSQL

-- This file and its contents are licensed under the Timescale License.
-- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license.
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE OR REPLACE FUNCTION run_continuous_agg_materialization(
hypertable REGCLASS,
materialization_table REGCLASS,
input_view NAME,
lowest_modified_value ANYELEMENT,
greatest_modified_value ANYELEMENT,
bucket_width "any",
input_view_schema NAME = 'public'
) RETURNS VOID AS :TSL_MODULE_PATHNAME, 'ts_run_continuous_agg_materialization' LANGUAGE C VOLATILE;
SET ROLE :ROLE_DEFAULT_PERM_USER;
CREATE TABLE continuous_agg_test(time BIGINT, data BIGINT, dummy BOOLEAN);
select create_hypertable('continuous_agg_test', 'time', chunk_time_interval=> 10);
-- simulated materialization table
CREATE TABLE materialization(time_bucket BIGINT, value BIGINT);
select create_hypertable('materialization', 'time_bucket', chunk_time_interval => 100);
SET ROLE :ROLE_SUPERUSER;
INSERT INTO _timescaledb_catalog.continuous_aggs_invalidation_threshold VALUES (1, 14);
SET ROLE :ROLE_DEFAULT_PERM_USER;
-- simulated continuous_agg insert view
CREATE VIEW test_view(time_bucket, value) AS
SELECT time_bucket(2, time), COUNT(data) as value
FROM continuous_agg_test
GROUP BY 1;
INSERT INTO continuous_agg_test VALUES (10, 1), (11, 2), (12, 3), (13, 4), (14, 1), (15, 1), (16, 1), (17, 1);
SELECT * FROM test_view ORDER BY 1;
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- materialize some of the data into the view
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 9, 12, 2);
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- materialize out of bounds is a nop
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 16, 19, 2);
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- materialize the rest of the data
SET ROLE :ROLE_SUPERUSER;
DELETE FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold WHERE hypertable_id = 1;
INSERT INTO _timescaledb_catalog.continuous_aggs_invalidation_threshold VALUES (1, 16);
SET ROLE :ROLE_DEFAULT_PERM_USER;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 12, 17, 2);
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- insert some additional data into the materialization table
-- (as if we had stale materializations)
INSERT INTO materialization VALUES
(11, 1),
(13, 3),
(15, 4);
SELECT * FROM materialization ORDER BY 1;
-- materializing should delete the invalid data, and leave the correct data
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 10, 15, 2);
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- test gaps
INSERT INTO continuous_agg_test VALUES
(9, 0), (10, 1), (11, 2), (12, 3), (13, 4), (20, 1), (21, 1);
SET ROLE :ROLE_SUPERUSER;
DELETE FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold WHERE hypertable_id = 1;
INSERT INTO _timescaledb_catalog.continuous_aggs_invalidation_threshold VALUES (1, 22);
SET ROLE :ROLE_DEFAULT_PERM_USER;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 9, 9, 2);
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- fill in the remaining
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 10, 12, 2);
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- the bucket containing big_int_max should not be materialized, but all others should
SELECT 9223372036854775807 as big_int_max \gset
SELECT -9223372036854775808 as big_int_min \gset
SET ROLE :ROLE_SUPERUSER;
DELETE FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold WHERE hypertable_id = 1;
INSERT INTO _timescaledb_catalog.continuous_aggs_invalidation_threshold VALUES (1, :big_int_max-1);
SET ROLE :ROLE_DEFAULT_PERM_USER;
INSERT INTO continuous_agg_test VALUES
(:big_int_max - 4, 1), (:big_int_max - 3, 5), (:big_int_max - 2, 7), (:big_int_max - 1, 9), (:big_int_max, 11),
(:big_int_min, 22), (:big_int_min + 1, 23);
SET client_min_messages TO error;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 10, 12, 2);
RESET client_min_messages;
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- test invalidations
SET client_min_messages TO error;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', :big_int_max-6, :big_int_max, 2);
RESET client_min_messages;
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
SET client_min_messages TO error;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', :big_int_min, :big_int_max, 2);
RESET client_min_messages;
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
TRUNCATE materialization;
-- test dropping columns
ALTER TABLE continuous_agg_test DROP COLUMN dummy;
SET client_min_messages TO error;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 9, 13, 2);
RESET client_min_messages;
SELECT * FROM materialization;
ALTER TABLE continuous_agg_test ADD COLUMN d2 int;
TRUNCATE materialization;
SET client_min_messages TO error;
SELECT run_continuous_agg_materialization('continuous_agg_test', 'materialization', 'test_view', 9, 13, 2);
RESET client_min_messages;
SELECT * FROM materialization;
TRUNCATE materialization;
-- name and view that needs quotes
CREATE VIEW "view with spaces"(time_bucket, value) AS
SELECT time_bucket(2, time), COUNT(data) as value
FROM continuous_agg_test
GROUP BY 1;
CREATE TABLE "table with spaces"(time_bucket BIGINT, value BIGINT);
select create_hypertable('"table with spaces"'::REGCLASS, 'time_bucket', chunk_time_interval => 100);
SET client_min_messages TO error;
SELECT run_continuous_agg_materialization('continuous_agg_test', '"table with spaces"', 'view with spaces', 9, 21, 2);
RESET client_min_messages;
SELECT * FROM "view with spaces" ORDER BY 1;
SELECT * FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
DROP TABLE materialization;
----------------------------
----------------------------
----------------------------
-- test with a time type
SET SESSION timezone TO 'UTC';
SET SESSION datestyle TO 'ISO';
CREATE TABLE materialization(time_bucket TIMESTAMPTZ, value BIGINT);
select create_hypertable('materialization', 'time_bucket');
CREATE TABLE continuous_agg_test_t(time TIMESTAMPTZ, data int);
select create_hypertable('continuous_agg_test_t', 'time');
INSERT INTO continuous_agg_test_t VALUES
('2019-02-02 2:00 UTC', 1),
('2019-02-02 3:00 UTC', 1),
('2019-02-02 4:00 UTC', 1),
('2019-02-02 5:00 UTC', 1);
SELECT * FROM continuous_agg_test_t;
TRUNCATE materialization;
SET ROLE :ROLE_SUPERUSER;
INSERT INTO _timescaledb_catalog.continuous_aggs_invalidation_threshold VALUES (5, _timescaledb_internal.time_to_internal('2019-02-02 4:00 UTC'::TIMESTAMPTZ));
TRUNCATE _timescaledb_catalog.continuous_aggs_completed_threshold;
SET ROLE :ROLE_DEFAULT_PERM_USER;
SET SESSION timezone TO 'UTC';
SET SESSION datestyle TO 'ISO';
CREATE VIEW test_view_t(time_bucket, value) AS
SELECT time_bucket('2 hours', time) as time_bucket, COUNT(data) as value
FROM continuous_agg_test_t
GROUP BY 1;
SELECT run_continuous_agg_materialization('continuous_agg_test_t', 'materialization', 'test_view_t'::NAME, '2019-02-02 2:00 UTC'::TIMESTAMPTZ, '2019-02-02 3:00 UTC'::TIMESTAMPTZ, '2 hours'::INTERVAL);
SELECT time_bucket, value FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = 4;
SELECT run_continuous_agg_materialization('continuous_agg_test_t', 'materialization', 'test_view_t'::NAME, '2019-02-02 4:00 UTC'::TIMESTAMPTZ, '2019-02-02 5:00 UTC'::TIMESTAMPTZ, '2 hours'::INTERVAL);
SELECT time_bucket, value FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = 4;
SET ROLE :ROLE_SUPERUSER;
DELETE FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold WHERE hypertable_id = 5;
INSERT INTO _timescaledb_catalog.continuous_aggs_invalidation_threshold VALUES (5, _timescaledb_internal.time_to_internal('2019-02-02 6:00 UTC'::TIMESTAMPTZ));
TRUNCATE _timescaledb_catalog.continuous_aggs_completed_threshold;
SET ROLE :ROLE_DEFAULT_PERM_USER;
SET SESSION timezone TO 'UTC';
SET SESSION datestyle TO 'ISO';
SELECT run_continuous_agg_materialization('continuous_agg_test_t', 'materialization', 'test_view_t'::NAME, '2019-02-02 4:00 UTC'::TIMESTAMPTZ, '2019-02-02 5:00 UTC'::TIMESTAMPTZ, '2 hours'::INTERVAL);
SELECT time_bucket, value FROM materialization ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = 4;
----------------------------
----------------------------
----------------------------
-- test with a real continuous aggregate
SET ROLE :ROLE_SUPERUSER;
TRUNCATE _timescaledb_catalog.continuous_aggs_completed_threshold;
TRUNCATE _timescaledb_catalog.continuous_aggs_invalidation_threshold;
SET ROLE :ROLE_DEFAULT_PERM_USER;
SET SESSION timezone TO 'UTC';
SET SESSION datestyle TO 'ISO';
SET client_min_messages TO LOG;
SELECT * FROM continuous_agg_test_t;
CREATE VIEW test_t_mat_view
WITH (timescaledb.continuous, timescaledb.materialized_only=true)
AS SELECT time_bucket('2 hours', time), COUNT(data) as value
FROM continuous_agg_test_t
GROUP BY 1;
SELECT mat_hypertable_id, raw_hypertable_id, user_view_schema, user_view_name,
partial_view_schema, partial_view_name,
_timescaledb_internal.to_timestamp(bucket_width), _timescaledb_internal.to_interval(refresh_lag),
job_id
FROM _timescaledb_catalog.continuous_agg;
SELECT mat_hypertable_id FROM _timescaledb_catalog.continuous_agg \gset
SET ROLE :ROLE_SUPERUSER;
UPDATE _timescaledb_catalog.continuous_agg
SET refresh_lag=7200000000
WHERE mat_hypertable_id=:mat_hypertable_id;
SET ROLE :ROLE_DEFAULT_PERM_USER;
SET SESSION timezone TO 'UTC';
SET SESSION datestyle TO 'ISO';
SELECT _timescaledb_internal.to_interval(refresh_lag)
FROM _timescaledb_catalog.continuous_agg;
SELECT ca.raw_hypertable_id as "RAW_HYPERTABLE_ID",
h.schema_name AS "MAT_SCHEMA_NAME",
h.table_name AS "MAT_TABLE_NAME",
partial_view_name as "PART_VIEW_NAME",
partial_view_schema as "PART_VIEW_SCHEMA"
FROM _timescaledb_catalog.continuous_agg ca
INNER JOIN _timescaledb_catalog.hypertable h ON(h.id = ca.mat_hypertable_id)
WHERE user_view_name = 'test_t_mat_view'
\gset
SELECT * FROM test_t_mat_view;
SELECT * FROM :"MAT_SCHEMA_NAME".:"MAT_TABLE_NAME" ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = :mat_hypertable_id;
SET timescaledb.current_timestamp_mock = '2019-02-02 5:00 UTC';
REFRESH MATERIALIZED VIEW test_t_mat_view;
SELECT * FROM :"MAT_SCHEMA_NAME".:"MAT_TABLE_NAME" ORDER BY 1;
SELECT * FROM test_t_mat_view ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = :mat_hypertable_id;
SELECT hypertable_id, _timescaledb_internal.to_timestamp(watermark) FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
REFRESH MATERIALIZED VIEW test_t_mat_view;
SELECT * FROM :"MAT_SCHEMA_NAME".:"MAT_TABLE_NAME" ORDER BY 1;
SELECT * FROM test_t_mat_view ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = :mat_hypertable_id;
SELECT hypertable_id, _timescaledb_internal.to_timestamp(watermark) FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- increase the current timestamp, so we actually materialize
SET timescaledb.current_timestamp_mock = '2019-02-02 7:00 UTC';
INSERT INTO continuous_agg_test_t VALUES ('2019-02-02 7:00 UTC', 1);
SELECT * FROM continuous_agg_test_t ORDER BY 1;
REFRESH MATERIALIZED VIEW test_t_mat_view;
SELECT * FROM test_t_mat_view ORDER BY 1;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = :mat_hypertable_id;
SELECT hypertable_id, _timescaledb_internal.to_timestamp(watermark) FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- test invalidations
INSERT INTO continuous_agg_test_t VALUES
('2019-02-02 2:00 UTC', 1),
('2019-02-02 3:00 UTC', 1),
('2019-02-02 4:00 UTC', 1),
('2019-02-02 5:00 UTC', 1);
SELECT * FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log;
REFRESH MATERIALIZED VIEW test_t_mat_view;
SELECT * FROM test_t_mat_view ORDER BY 1;
SELECT * FROM _timescaledb_catalog.continuous_aggs_completed_threshold;
SELECT materialization_id, _timescaledb_internal.to_timestamp(watermark)
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id = :mat_hypertable_id;
SELECT hypertable_id, _timescaledb_internal.to_timestamp(watermark) FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold;
-- test extremes
CREATE TABLE continuous_agg_extreme(time BIGINT, data BIGINT);
SELECT create_hypertable('continuous_agg_extreme', 'time', chunk_time_interval=> 10);
CREATE OR REPLACE FUNCTION integer_now_continuous_agg_extreme() returns BIGINT LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), BIGINT '-9223372036854775808') FROM continuous_agg_extreme $$;
SELECT set_integer_now_func('continuous_agg_extreme', 'integer_now_continuous_agg_extreme');
-- We should be able to use time_bucket(5, ...) (note lack of '), but that is currently not
-- recognized as a constant
CREATE VIEW extreme_view
WITH (timescaledb.continuous, timescaledb.materialized_only=true)
AS SELECT time_bucket('1', time), SUM(data) as value
FROM continuous_agg_extreme
GROUP BY 1;
SELECT id as raw_table_id FROM _timescaledb_catalog.hypertable WHERE table_name='continuous_agg_extreme' \gset
SELECT mat_hypertable_id FROM _timescaledb_catalog.continuous_agg WHERE raw_hypertable_id=:raw_table_id \gset
-- EMPTY table should be a nop
REFRESH MATERIALIZED VIEW extreme_view;
SELECT * FROM extreme_view;
SELECT materialization_id, watermark
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id=:mat_hypertable_id;
SELECT hypertable_id, watermark
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
WHERE hypertable_id=:raw_table_id;
-- less than a bucket above MIN should be a nop
INSERT INTO continuous_agg_extreme VALUES
(:big_int_min, 1);
REFRESH MATERIALIZED VIEW extreme_view;
SELECT * FROM extreme_view;
SELECT materialization_id, watermark
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id=:mat_hypertable_id;
SELECT hypertable_id, watermark
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
WHERE hypertable_id=:raw_table_id;
-- but we will be able to materialize it once we have enough values
INSERT INTO continuous_agg_extreme VALUES
(:big_int_min+10, 11);
REFRESH MATERIALIZED VIEW extreme_view;
SELECT * FROM extreme_view;
SELECT materialization_id, watermark
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id=:mat_hypertable_id;
SELECT hypertable_id, watermark
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
WHERE hypertable_id=:raw_table_id;
-- we don't materialize the max value, but attempting will materialize the entire
-- table up to the materialization limit
INSERT INTO continuous_agg_extreme VALUES
(100, 101),
(:big_int_max-5, 201),
(:big_int_max-4, 201),
(:big_int_max-3, 201),
(:big_int_max-2, 201),
(:big_int_max-1, 201),
(:big_int_max, :big_int_max);
REFRESH MATERIALIZED VIEW extreme_view;
SELECT * FROM extreme_view ORDER BY 1;
SELECT materialization_id, watermark
FROM _timescaledb_catalog.continuous_aggs_completed_threshold
WHERE materialization_id=:mat_hypertable_id;
SELECT hypertable_id, watermark
FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold
WHERE hypertable_id=:raw_table_id;
--cleanup of continuous agg views --
DROP view test_t_mat_view CASCADE;
DROP view extreme_view CASCADE;
-- negative lag test
CREATE TABLE continuous_agg_negative(time BIGINT, data BIGINT);
SELECT create_hypertable('continuous_agg_negative', 'time', chunk_time_interval=> 10);
CREATE OR REPLACE FUNCTION integer_now_continuous_agg_negative() returns BIGINT LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), BIGINT '-9223372036854775808') FROM continuous_agg_negative $$;
SELECT set_integer_now_func('continuous_agg_negative', 'integer_now_continuous_agg_negative');
CREATE VIEW negative_view_5
WITH (timescaledb.continuous, timescaledb.materialized_only=true, timescaledb.refresh_lag='-2')
AS SELECT time_bucket('5', time), COUNT(data) as value
FROM continuous_agg_negative
GROUP BY 1;
-- two chunks, 4 buckets
INSERT INTO continuous_agg_negative
SELECT i, i FROM generate_series(0, 11) AS i;
REFRESH MATERIALIZED VIEW negative_view_5;
SELECT * FROM negative_view_5 ORDER BY 1;
-- inserting 12 and 13 will cause the next bucket to materialize
-- even though the time_bucket would require us INSERT 14
INSERT INTO continuous_agg_negative VALUES (12, 12), (13, 13);
REFRESH MATERIALIZED VIEW negative_view_5;
SELECT * FROM negative_view_5 ORDER BY 1;
-- bucket is finished as normal with the additional value
INSERT INTO continuous_agg_negative VALUES (14, 14);
REFRESH MATERIALIZED VIEW negative_view_5;
SELECT * FROM negative_view_5 ORDER BY 1;
--inserting a really large value does not work because of max_interval_per_job
INSERT INTO continuous_agg_negative VALUES (:big_int_max-3, 201);
REFRESH MATERIALIZED VIEW negative_view_5;
SELECT * FROM negative_view_5 ORDER BY 1;
DROP VIEW negative_view_5 CASCADE;
TRUNCATE continuous_agg_negative;
CREATE VIEW negative_view_5
WITH (timescaledb.continuous, timescaledb.materialized_only=true, timescaledb.refresh_lag='-2')
AS SELECT time_bucket('5', time), COUNT(data) as value
FROM continuous_agg_negative
GROUP BY 1;
-- we can handle values near max
INSERT INTO continuous_agg_negative VALUES (:big_int_max-3, 201);
SET client_min_messages TO error;
REFRESH MATERIALIZED VIEW negative_view_5;
RESET client_min_messages;
SELECT * FROM negative_view_5 ORDER BY 1;
-- even when the subtraction would make a completion time greater than max
INSERT INTO continuous_agg_negative VALUES (:big_int_max-1, 201);
SET client_min_messages TO error;
REFRESH MATERIALIZED VIEW negative_view_5;
RESET client_min_messages;
SELECT * FROM negative_view_5 ORDER BY 1;
DROP TABLE continuous_agg_negative CASCADE;
-- max_interval_per_job tests
CREATE TABLE continuous_agg_max_mat(time BIGINT, data BIGINT);
SELECT create_hypertable('continuous_agg_max_mat', 'time', chunk_time_interval=> 10);
CREATE OR REPLACE FUNCTION integer_now_continuous_agg_max_mat() returns BIGINT LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), BIGINT '-9223372036854775808') FROM continuous_agg_max_mat $$;
SELECT set_integer_now_func('continuous_agg_max_mat', 'integer_now_continuous_agg_max_mat');
-- only allow two time_buckets per run
CREATE VIEW max_mat_view
WITH (timescaledb.continuous, timescaledb.materialized_only=true, timescaledb.max_interval_per_job='4', timescaledb.refresh_lag='-2')
AS SELECT time_bucket('2', time), COUNT(data) as value
FROM continuous_agg_max_mat
GROUP BY 1;
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(0, 10) AS i;
SET client_min_messages TO LOG;
-- first run create two materializations
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
-- repeated runs will eventually materialize all the data
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
--one invalidation covered by max_interval refreshed right away
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(0, 3) AS i;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
--nothing to do
REFRESH MATERIALIZED VIEW max_mat_view;
--one invalidation too big for max_interval will be split
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(0, 6) AS i;
REFRESH MATERIALIZED VIEW max_mat_view;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
--nothing to do
REFRESH MATERIALIZED VIEW max_mat_view;
--many invalidation too big for max_interval will be split
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(0, 1) AS i;
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(2, 3) AS i;
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(4, 5) AS i;
REFRESH MATERIALIZED VIEW max_mat_view;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
--nothing to do
REFRESH MATERIALIZED VIEW max_mat_view;
--one invalidation + new entries requires two refreshes if the refresh budget taken up by invalidation
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(0, 3) AS i;
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(11, 12) AS i;
REFRESH MATERIALIZED VIEW max_mat_view;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
--nothing to do
REFRESH MATERIALIZED VIEW max_mat_view;
--one invalidation + new entries done in one refresh if the refresh budget allows
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(0, 1) AS i;
INSERT INTO continuous_agg_max_mat SELECT i, i FROM generate_series(14, 15) AS i;
REFRESH MATERIALIZED VIEW max_mat_view;
SELECT * FROM max_mat_view ORDER BY 1;
--nothing to do.
REFRESH MATERIALIZED VIEW max_mat_view;
-- time type
CREATE TABLE continuous_agg_max_mat_t(time TIMESTAMPTZ, data TIMESTAMPTZ);
SELECT create_hypertable('continuous_agg_max_mat_t', 'time');
-- only allow two time_buckets per run
CREATE VIEW max_mat_view_t
WITH (timescaledb.continuous, timescaledb.materialized_only=true, timescaledb.max_interval_per_job='4 hours', timescaledb.refresh_lag='-2 hours')
AS SELECT time_bucket('2 hours', time), COUNT(data) as value
FROM continuous_agg_max_mat_t
GROUP BY 1;
INSERT INTO continuous_agg_max_mat_t
SELECT i, i FROM
generate_series('2019-09-09 1:00'::TIMESTAMPTZ, '2019-09-09 10:00', '1 hour') AS i;
SET timescaledb.current_timestamp_mock = '2019-09-09 10:00 UTC';
-- first run create two materializations
REFRESH MATERIALIZED VIEW max_mat_view_t;
SELECT * FROM max_mat_view_t ORDER BY 1;
-- repeated runs will eventually materialize all the data
REFRESH MATERIALIZED VIEW max_mat_view_t;
SELECT * FROM max_mat_view_t ORDER BY 1;
REFRESH MATERIALIZED VIEW max_mat_view_t;
SELECT * FROM max_mat_view_t ORDER BY 1;
REFRESH MATERIALIZED VIEW max_mat_view_t;
SELECT * FROM max_mat_view_t ORDER BY 1;
-- regular timestamp
CREATE TABLE continuous_agg_max_mat_timestamp(time TIMESTAMP);
SELECT create_hypertable('continuous_agg_max_mat_timestamp', 'time');
CREATE VIEW max_mat_view_timestamp
WITH (timescaledb.continuous, timescaledb.materialized_only=true, timescaledb.refresh_lag='-2 hours')
AS SELECT time_bucket('2 hours', time)
FROM continuous_agg_max_mat_timestamp
GROUP BY 1;
INSERT INTO continuous_agg_max_mat_timestamp
SELECT generate_series('2019-09-09 1:00'::TIMESTAMPTZ, '2019-09-09 10:00', '1 hour');
-- first materializes everything
REFRESH MATERIALIZED VIEW max_mat_view_timestamp;
SELECT * FROM max_mat_view_timestamp ORDER BY 1;
-- date
CREATE TABLE continuous_agg_max_mat_date(time DATE);
SELECT create_hypertable('continuous_agg_max_mat_date', 'time');
CREATE VIEW max_mat_view_date
WITH (timescaledb.continuous, timescaledb.materialized_only=true, timescaledb.refresh_lag='-7 days')
AS SELECT time_bucket('7 days', time)
FROM continuous_agg_max_mat_date
GROUP BY 1;
INSERT INTO continuous_agg_max_mat_date
SELECT generate_series('2019-09-01'::DATE, '2019-09-010 10:00', '1 day');
SET timescaledb.current_timestamp_mock = '2019-09-09 01:00 UTC';
--SET timescaledb.current_timestamp_mock = '2019-09-09 01:01:01 UTC';
-- first materializes everything
REFRESH MATERIALIZED VIEW max_mat_view_date;
SELECT * FROM max_mat_view_date ORDER BY 1;
SELECT view_name, completed_threshold, invalidation_threshold, job_id, job_status, last_run_duration
FROM timescaledb_information.continuous_aggregate_stats ORDER BY 1;
SELECT view_name, refresh_lag, max_interval_per_job
FROM timescaledb_information.continuous_aggregates ORDER BY 1;
SET SESSION timezone TO 'EST';
SELECT view_name, completed_threshold, invalidation_threshold, job_id, job_status, last_run_duration
FROM timescaledb_information.continuous_aggregate_stats ORDER BY 1;
SELECT view_name, refresh_lag, max_interval_per_job
FROM timescaledb_information.continuous_aggregates ORDER BY 1;
-- test timezone is respected when materializing cagg with TIMESTAMP time column
RESET timescaledb.current_timestamp_mock;
RESET client_min_messages;
SET SESSION timezone TO 'GMT+5';
CREATE TABLE timezone_test(time timestamp NOT NULL);
SELECT table_name FROM create_hypertable('timezone_test','time');
INSERT INTO timezone_test VALUES (now() - '30m'::interval), (now()), (now() + '30m'::interval);
CREATE VIEW timezone_test_summary
WITH (timescaledb.continuous,timescaledb.materialized_only=true)
AS SELECT time_bucket('5m', time)
FROM timezone_test
GROUP BY 1;
REFRESH MATERIALIZED VIEW timezone_test_summary;
-- this must return 1 as only 1 row is in the materialization interval
SELECT count(*) FROM timezone_test_summary;
DROP TABLE timezone_test CASCADE;
-- repeat test with timezone with negative offset
SET SESSION timezone TO 'GMT-5';
CREATE TABLE timezone_test(time timestamp NOT NULL);
SELECT table_name FROM create_hypertable('timezone_test','time');
INSERT INTO timezone_test VALUES (now() - '30m'::interval), (now()), (now() + '30m'::interval);
CREATE VIEW timezone_test_summary
WITH (timescaledb.continuous,timescaledb.materialized_only=true)
AS SELECT time_bucket('5m', time)
FROM timezone_test
GROUP BY 1;
REFRESH MATERIALIZED VIEW timezone_test_summary;
-- this must return 1 as only 1 row is in the materialization interval
SELECT count(*) FROM timezone_test_summary;
DROP TABLE timezone_test CASCADE;
-- TESTS for integer based table to verify watermark limited by max value of time column and not by now
CREATE TABLE continuous_agg_int(time BIGINT, data BIGINT);
SELECT create_hypertable('continuous_agg_int', 'time', chunk_time_interval=> 10);
CREATE OR REPLACE FUNCTION integer_now_continuous_agg_max() returns BIGINT LANGUAGE SQL STABLE as $$ SELECT BIGINT '9223372036854775807' $$;
SELECT set_integer_now_func('continuous_agg_int', 'integer_now_continuous_agg_max');
CREATE VIEW continuous_agg_int_max
WITH (timescaledb.continuous, timescaledb.refresh_lag='0')
AS SELECT time_bucket('10', time), COUNT(data) as value
FROM continuous_agg_int
GROUP BY 1;
INSERT INTO continuous_agg_int values (-10, 100), (1,100), (10, 100);
select chunk_table, ranges from chunk_relation_size('continuous_agg_int');
REFRESH MATERIALIZED VIEW continuous_agg_int_max;
REFRESH MATERIALIZED VIEW continuous_agg_int_max;
REFRESH MATERIALIZED VIEW continuous_agg_int_max;
select * from continuous_agg_int_max;
--watermark is 20
SELECT view_name, completed_threshold, invalidation_threshold
FROM timescaledb_information.continuous_aggregate_stats
where view_name::text like 'continuous_agg_int_max';
-- TEST that watermark is limited by max value from data and not by now()
CREATE TABLE continuous_agg_ts_max_t(timecol TIMESTAMPTZ, data integer);
SELECT create_hypertable('continuous_agg_ts_max_t', 'timecol', chunk_time_interval=>'365 days'::interval);
CREATE VIEW continuous_agg_ts_max_view
WITH (timescaledb.continuous, timescaledb.max_interval_per_job='365 days', timescaledb.refresh_lag='-2 hours')
AS SELECT time_bucket('2 hours', timecol), COUNT(data) as value
FROM continuous_agg_ts_max_t
GROUP BY 1;
INSERT INTO continuous_agg_ts_max_t
values ('1969-01-01 1:00'::timestamptz, 10);
REFRESH MATERIALIZED VIEW continuous_agg_ts_max_view;
SELECT view_name, completed_threshold, invalidation_threshold
FROM timescaledb_information.continuous_aggregate_stats
where view_name::text like 'continuous_agg_ts_max_view';
INSERT INTO continuous_agg_ts_max_t
values ('1970-01-01 1:00'::timestamptz, 10);
select chunk_table, ranges from chunk_relation_size('continuous_agg_ts_max_t');
REFRESH MATERIALIZED VIEW continuous_agg_ts_max_view;
REFRESH MATERIALIZED VIEW continuous_agg_ts_max_view;
SELECT view_name, completed_threshold, invalidation_threshold
FROM timescaledb_information.continuous_aggregate_stats
where view_name::text like 'continuous_agg_ts_max_view';
-- no more new data to materialize, threshold should not change
REFRESH MATERIALIZED VIEW continuous_agg_ts_max_view;
SELECT view_name, completed_threshold, invalidation_threshold
FROM timescaledb_information.continuous_aggregate_stats
where view_name::text like 'continuous_agg_ts_max_view';