mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-22 05:31:41 +08:00
Change the prefix for continuous aggregate tests from continuous_aggs_ to cagg_. This is similar to commit 6a8c2b66 which did this adjustment for isolation tests because we were running into length limitations for the spec name. This patch adjusts the remaining tests to be consistent with the naming used in isolation tests.
314 lines
10 KiB
PL/PgSQL
314 lines
10 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.
|
|
|
|
-- Disable background workers since we are testing manual refresh
|
|
\c :TEST_DBNAME :ROLE_SUPERUSER
|
|
SELECT _timescaledb_internal.stop_background_workers();
|
|
SET ROLE :ROLE_DEFAULT_PERM_USER;
|
|
|
|
CREATE TABLE conditions (time timestamptz NOT NULL, device int, temp float);
|
|
SELECT create_hypertable('conditions', 'time');
|
|
|
|
SELECT setseed(.12);
|
|
|
|
INSERT INTO conditions
|
|
SELECT t, ceil(abs(timestamp_hash(t::timestamp))%4)::int, abs(timestamp_hash(t::timestamp))%40
|
|
FROM generate_series('2020-05-01', '2020-05-05', '10 minutes'::interval) t;
|
|
|
|
-- Show the most recent data
|
|
SELECT * FROM conditions
|
|
ORDER BY time DESC, device
|
|
LIMIT 10;
|
|
|
|
CREATE MATERIALIZED VIEW daily_temp
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('1 day', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
|
|
-- The continuous aggregate should be empty
|
|
SELECT * FROM daily_temp
|
|
ORDER BY day DESC, device;
|
|
|
|
-- Refresh one bucket (1 day):
|
|
SHOW timezone;
|
|
-- The refresh of a single bucket must align with the start of the day
|
|
-- in the bucket's time zone (which is UTC, since time_bucket doesn't
|
|
-- support time zone arg)
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03 00:00 UTC', '2020-05-04 00:00 UTC');
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03 17:00 PDT', '2020-05-04 17:00 PDT');
|
|
|
|
\set ON_ERROR_STOP 0
|
|
\set VERBOSITY default
|
|
-- These refreshes will fail since they don't align with the bucket's
|
|
-- time zone
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03', '2020-05-04');
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03 00:00 PDT', '2020-05-04 00:00 PDT');
|
|
|
|
-- Refresh window less than one bucket
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03 00:00 UTC', '2020-05-03 23:59 UTC');
|
|
-- Refresh window bigger than one bucket, but failing since it is not
|
|
-- aligned with bucket boundaries so that it covers a full bucket:
|
|
--
|
|
-- Refresh window: [----------)
|
|
-- Buckets: [------|------]
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03 01:00 UTC', '2020-05-04 08:00 UTC');
|
|
\set VERBOSITY terse
|
|
\set ON_ERROR_STOP 1
|
|
|
|
-- Refresh the most recent few days:
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-02', '2020-05-05 17:00');
|
|
|
|
SELECT * FROM daily_temp
|
|
ORDER BY day DESC, device;
|
|
|
|
-- Refresh the rest (and try DEBUG output)
|
|
SET client_min_messages TO DEBUG1;
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-04-30', '2020-05-04');
|
|
RESET client_min_messages;
|
|
|
|
-- Compare the aggregate to the equivalent query on the source table
|
|
SELECT * FROM daily_temp
|
|
ORDER BY day DESC, device;
|
|
|
|
SELECT time_bucket('1 day', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2
|
|
ORDER BY 1 DESC,2;
|
|
|
|
-- Test unusual, but valid input
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-01'::timestamptz, '2020-05-03'::date);
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-01'::date, '2020-05-03'::date);
|
|
|
|
-- Unbounded window forward in time
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03', NULL);
|
|
CALL refresh_continuous_aggregate('daily_temp', NULL, NULL);
|
|
|
|
-- Unbounded window back in time
|
|
CALL refresh_continuous_aggregate('daily_temp', NULL, '2020-05-01');
|
|
|
|
-- Test bad input
|
|
\set ON_ERROR_STOP 0
|
|
-- Bad continuous aggregate name
|
|
CALL refresh_continuous_aggregate(NULL, '2020-05-03', '2020-05-05');
|
|
CALL refresh_continuous_aggregate('xyz', '2020-05-03', '2020-05-05');
|
|
-- Valid object, but not a continuous aggregate
|
|
CALL refresh_continuous_aggregate('conditions', '2020-05-03', '2020-05-05');
|
|
-- Object ID with no object
|
|
CALL refresh_continuous_aggregate(1, '2020-05-03', '2020-05-05');
|
|
-- Lacking arguments
|
|
CALL refresh_continuous_aggregate('daily_temp');
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03');
|
|
-- Bad time ranges
|
|
CALL refresh_continuous_aggregate('daily_temp', 'xyz', '2020-05-05');
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03', 'xyz');
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-03', '2020-05-01');
|
|
-- Bad time input
|
|
CALL refresh_continuous_aggregate('daily_temp', '2020-05-01'::text, '2020-05-03'::text);
|
|
CALL refresh_continuous_aggregate('daily_temp', 0, '2020-05-01');
|
|
\set ON_ERROR_STOP 1
|
|
|
|
-- Test different time types
|
|
CREATE TABLE conditions_date (time date NOT NULL, device int, temp float);
|
|
SELECT create_hypertable('conditions_date', 'time');
|
|
|
|
CREATE MATERIALIZED VIEW daily_temp_date
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('1 day', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions_date
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
|
|
CALL refresh_continuous_aggregate('daily_temp_date', '2020-05-01', '2020-05-03');
|
|
|
|
-- Try max refresh window size
|
|
CALL refresh_continuous_aggregate('daily_temp_date', NULL, NULL);
|
|
|
|
-- Test smallint-based continuous aggregate
|
|
CREATE TABLE conditions_smallint (time smallint NOT NULL, device int, temp float);
|
|
SELECT create_hypertable('conditions_smallint', 'time', chunk_time_interval => 20);
|
|
|
|
INSERT INTO conditions_smallint
|
|
SELECT t, ceil(abs(timestamp_hash(to_timestamp(t)::timestamp))%4)::smallint, abs(timestamp_hash(to_timestamp(t)::timestamp))%40
|
|
FROM generate_series(1, 100, 1) t;
|
|
|
|
CREATE OR REPLACE FUNCTION smallint_now()
|
|
RETURNS smallint LANGUAGE SQL STABLE AS
|
|
$$
|
|
SELECT coalesce(max(time), 0)::smallint
|
|
FROM conditions_smallint
|
|
$$;
|
|
|
|
\set ON_ERROR_STOP 0
|
|
-- First try to create an integer-based continuous aggregate without
|
|
-- an now function. This should not be allowed.
|
|
CREATE MATERIALIZED VIEW cond_20_smallint
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket(SMALLINT '20', time) AS bucket, device, avg(temp) AS avg_temp
|
|
FROM conditions_smallint c
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
\set ON_ERROR_STOP 1
|
|
|
|
SELECT set_integer_now_func('conditions_smallint', 'smallint_now');
|
|
|
|
CREATE MATERIALIZED VIEW cond_20_smallint
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket(SMALLINT '20', time) AS bucket, device, avg(temp) AS avg_temp
|
|
FROM conditions_smallint c
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
|
|
CALL refresh_continuous_aggregate('cond_20_smallint', 0::smallint, 70::smallint);
|
|
|
|
SELECT * FROM cond_20_smallint
|
|
ORDER BY 1,2;
|
|
|
|
-- Try max refresh window size
|
|
CALL refresh_continuous_aggregate('cond_20_smallint', NULL, NULL);
|
|
|
|
-- Test int-based continuous aggregate
|
|
CREATE TABLE conditions_int (time int NOT NULL, device int, temp float);
|
|
SELECT create_hypertable('conditions_int', 'time', chunk_time_interval => 20);
|
|
|
|
INSERT INTO conditions_int
|
|
SELECT t, ceil(abs(timestamp_hash(to_timestamp(t)::timestamp))%4)::int, abs(timestamp_hash(to_timestamp(t)::timestamp))%40
|
|
FROM generate_series(1, 100, 1) t;
|
|
|
|
CREATE OR REPLACE FUNCTION int_now()
|
|
RETURNS int LANGUAGE SQL STABLE AS
|
|
$$
|
|
SELECT coalesce(max(time), 0)
|
|
FROM conditions_int
|
|
$$;
|
|
|
|
SELECT set_integer_now_func('conditions_int', 'int_now');
|
|
|
|
CREATE MATERIALIZED VIEW cond_20_int
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket(INT '20', time) AS bucket, device, avg(temp) AS avg_temp
|
|
FROM conditions_int
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
|
|
CALL refresh_continuous_aggregate('cond_20_int', 0, 65);
|
|
|
|
SELECT * FROM cond_20_int
|
|
ORDER BY 1,2;
|
|
|
|
-- Try max refresh window size
|
|
CALL refresh_continuous_aggregate('cond_20_int', NULL, NULL);
|
|
|
|
-- Test bigint-based continuous aggregate
|
|
CREATE TABLE conditions_bigint (time bigint NOT NULL, device int, temp float);
|
|
SELECT create_hypertable('conditions_bigint', 'time', chunk_time_interval => 20);
|
|
|
|
INSERT INTO conditions_bigint
|
|
SELECT t, ceil(abs(timestamp_hash(to_timestamp(t)::timestamp))%4)::bigint, abs(timestamp_hash(to_timestamp(t)::timestamp))%40
|
|
FROM generate_series(1, 100, 1) t;
|
|
|
|
CREATE OR REPLACE FUNCTION bigint_now()
|
|
RETURNS bigint LANGUAGE SQL STABLE AS
|
|
$$
|
|
SELECT coalesce(max(time), 0)::bigint
|
|
FROM conditions_bigint
|
|
$$;
|
|
|
|
SELECT set_integer_now_func('conditions_bigint', 'bigint_now');
|
|
|
|
CREATE MATERIALIZED VIEW cond_20_bigint
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket(BIGINT '20', time) AS bucket, device, avg(temp) AS avg_temp
|
|
FROM conditions_bigint
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
|
|
CALL refresh_continuous_aggregate('cond_20_bigint', 0, 75);
|
|
|
|
SELECT * FROM cond_20_bigint
|
|
ORDER BY 1,2;
|
|
|
|
-- Try max refresh window size
|
|
CALL refresh_continuous_aggregate('cond_20_bigint', NULL, NULL);
|
|
|
|
-- Test that WITH NO DATA and WITH DATA works (we use whatever is the
|
|
-- default for Postgres, so we do not need to have test for the
|
|
-- default).
|
|
|
|
CREATE MATERIALIZED VIEW weekly_temp_without_data
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('7 days', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
|
|
CREATE MATERIALIZED VIEW weekly_temp_with_data
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('7 days', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH DATA;
|
|
|
|
SELECT * FROM weekly_temp_without_data;
|
|
SELECT * FROM weekly_temp_with_data ORDER BY 1,2;
|
|
|
|
\set ON_ERROR_STOP 0
|
|
-- REFRESH MATERIALIZED VIEW is blocked on continuous aggregates
|
|
REFRESH MATERIALIZED VIEW weekly_temp_without_data;
|
|
|
|
-- These should fail since we do not allow refreshing inside a
|
|
-- transaction, not even as part of CREATE MATERIALIZED VIEW.
|
|
DO LANGUAGE PLPGSQL $$ BEGIN
|
|
CREATE MATERIALIZED VIEW weekly_conditions
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('7 days', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH DATA;
|
|
END $$;
|
|
|
|
BEGIN;
|
|
CREATE MATERIALIZED VIEW weekly_conditions
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('7 days', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH DATA;
|
|
COMMIT;
|
|
|
|
\set ON_ERROR_STOP 1
|
|
|
|
-- This should not fail since we do not refresh the continuous
|
|
-- aggregate.
|
|
DO LANGUAGE PLPGSQL $$ BEGIN
|
|
CREATE MATERIALIZED VIEW weekly_conditions_1
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('7 days', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
END $$;
|
|
|
|
BEGIN;
|
|
CREATE MATERIALIZED VIEW weekly_conditions_2
|
|
WITH (timescaledb.continuous,
|
|
timescaledb.materialized_only=true)
|
|
AS
|
|
SELECT time_bucket('7 days', time) AS day, device, avg(temp) AS avg_temp
|
|
FROM conditions
|
|
GROUP BY 1,2 WITH NO DATA;
|
|
COMMIT;
|