Skip to content

Commit

Permalink
Fix refresh on empty CAgg with variable bucket
Browse files Browse the repository at this point in the history
So far, we have not handled CAggs with variable buckets correctly. The
CAgg refresh on a hypertable without any data lead to the error message
"timestamp out of range". This patch fixes the problem by declaring
empty CAggs as up-to-date.
  • Loading branch information
jnidzwetzki committed Feb 16, 2024
1 parent b01c8e7 commit 1f217ed
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 3 deletions.
1 change: 1 addition & 0 deletions .unreleased/bugfix_6660
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes: #6660 Fix refresh on empty CAgg with variable bucket
15 changes: 12 additions & 3 deletions tsl/src/continuous_aggs/refresh.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,9 +824,18 @@ continuous_agg_refresh_internal(const ContinuousAgg *cagg,
if (refresh_window.end > invalidation_threshold)
refresh_window.end = invalidation_threshold;

/* Capping the end might have made the window 0, or negative, so
* nothing to refresh in that case */
if (refresh_window.start >= refresh_window.end)
/* Capping the end might have made the window 0, or negative, so nothing to refresh in that
* case.
*
* For variable width buckets we use a refresh_window.start value that is lower than the
* -infinity value (ts_time_get_nobegin < ts_time_get_min). Therefore, the first check in the
* following if statement is not enough. If the invalidation_threshold returns the min_value for
* the data type, we end up with [nobegin, min_value] which is an invalid time interval.
* Therefore, we have also to check if the invalidation_threshold is defined. If not, no refresh
* is needed. */
if ((refresh_window.start >= refresh_window.end) ||
(IS_TIMESTAMP_TYPE(refresh_window.type) &&
invalidation_threshold == ts_time_get_min(refresh_window.type)))
{
emit_up_to_date_notice(cagg, callctx);

Expand Down
49 changes: 49 additions & 0 deletions tsl/test/expected/cagg_invalidation.out
Original file line number Diff line number Diff line change
Expand Up @@ -1226,3 +1226,52 @@ CALL refresh_continuous_aggregate('cond_10', 0, 200);
WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window"
DETAIL: Expected an integer but current value is "-".
\set VERBOSITY terse
-- Test refresh with undefined invalidation threshold and variable sized buckets
CREATE TABLE timestamp_ht (
time timestamptz NOT NULL,
value float
);
SELECT create_hypertable('timestamp_ht', 'time');
create_hypertable
---------------------------
(9,public,timestamp_ht,t)
(1 row)

CREATE MATERIALIZED VIEW temperature_4h
WITH (timescaledb.continuous) AS
SELECT time_bucket('4 hour', time), avg(value)
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;
NOTICE: continuous aggregate "temperature_4h" is already up-to-date
-- We also treat time_buckets with an hourly interval that uses a time-zone
-- as a variable see caggtimebucket_validate().
CREATE MATERIALIZED VIEW temperature_4h_2
WITH (timescaledb.continuous) AS
SELECT time_bucket('4 hour', time, 'Europe/Berlin') AS bucket_4h, avg(value) AS average
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;
NOTICE: continuous aggregate "temperature_4h_2" is already up-to-date
CREATE MATERIALIZED VIEW temperature_1month
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', time), avg(value)
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;
NOTICE: continuous aggregate "temperature_1month" is already up-to-date
CREATE MATERIALIZED VIEW temperature_1month_ts
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', time, 'Europe/Berlin'), avg(value)
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;
NOTICE: continuous aggregate "temperature_1month_ts" is already up-to-date
CREATE MATERIALIZED VIEW temperature_1month_hierarchical
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', bucket_4h), avg(average)
FROM temperature_4h_2
GROUP BY 1 ORDER BY 1;
NOTICE: continuous aggregate "temperature_1month_hierarchical" is already up-to-date
CREATE MATERIALIZED VIEW temperature_1month_hierarchical_ts
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', bucket_4h, 'Europe/Berlin'), avg(average)
FROM temperature_4h_2
GROUP BY 1 ORDER BY 1;
NOTICE: continuous aggregate "temperature_1month_hierarchical_ts" is already up-to-date
46 changes: 46 additions & 0 deletions tsl/test/sql/cagg_invalidation.sql
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,49 @@ SET timescaledb.materializations_per_refresh_window='-';
INSERT INTO conditions VALUES (140, 1, 1.0);
CALL refresh_continuous_aggregate('cond_10', 0, 200);
\set VERBOSITY terse

-- Test refresh with undefined invalidation threshold and variable sized buckets
CREATE TABLE timestamp_ht (
time timestamptz NOT NULL,
value float
);

SELECT create_hypertable('timestamp_ht', 'time');

CREATE MATERIALIZED VIEW temperature_4h
WITH (timescaledb.continuous) AS
SELECT time_bucket('4 hour', time), avg(value)
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;

-- We also treat time_buckets with an hourly interval that uses a time-zone
-- as a variable see caggtimebucket_validate().
CREATE MATERIALIZED VIEW temperature_4h_2
WITH (timescaledb.continuous) AS
SELECT time_bucket('4 hour', time, 'Europe/Berlin') AS bucket_4h, avg(value) AS average
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;

CREATE MATERIALIZED VIEW temperature_1month
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', time), avg(value)
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;

CREATE MATERIALIZED VIEW temperature_1month_ts
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', time, 'Europe/Berlin'), avg(value)
FROM timestamp_ht
GROUP BY 1 ORDER BY 1;

CREATE MATERIALIZED VIEW temperature_1month_hierarchical
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', bucket_4h), avg(average)
FROM temperature_4h_2
GROUP BY 1 ORDER BY 1;

CREATE MATERIALIZED VIEW temperature_1month_hierarchical_ts
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 month', bucket_4h, 'Europe/Berlin'), avg(average)
FROM temperature_4h_2
GROUP BY 1 ORDER BY 1;

0 comments on commit 1f217ed

Please sign in to comment.