diff --git a/.unreleased/pr_9717 b/.unreleased/pr_9717 new file mode 100644 index 00000000000..95484349fd2 --- /dev/null +++ b/.unreleased/pr_9717 @@ -0,0 +1 @@ +Fixes: #9717 Reject non-positive time bucket width on cagg creation diff --git a/tsl/src/continuous_aggs/common.c b/tsl/src/continuous_aggs/common.c index 3519e9ea3ac..b6d4da5b24b 100644 --- a/tsl/src/continuous_aggs/common.c +++ b/tsl/src/continuous_aggs/common.c @@ -435,6 +435,13 @@ process_timebucket_parameters(FuncExpr *fe, ContinuousAggBucketFunction *bf, boo bf->bucket_function = fe->funcid; bf->bucket_time_based = ts_continuous_agg_bucket_on_interval(bf->bucket_function); bf->bucket_fixed_interval = time_bucket_info_has_fixed_width(bf); + + if (process_checks && is_cagg_create && ts_continuous_agg_bucket_width(bf) <= 0) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("time bucket width must be greater than zero"))); + } } /* diff --git a/tsl/test/expected/cagg_errors.out b/tsl/test/expected/cagg_errors.out index 7ac658d016d..4a7dba32488 100644 --- a/tsl/test/expected/cagg_errors.out +++ b/tsl/test/expected/cagg_errors.out @@ -230,6 +230,29 @@ FROM conditions GROUP BY 1 WITH NO DATA; ERROR: invalid bucket width for time bucket function +-- negative or zero bucket width must be rejected at creation time; +-- otherwise refresh later trips Assert(bucket_width > 0). +CREATE MATERIALIZED VIEW mat_neg WITH (timescaledb.continuous) +AS +SELECT time_bucket('-1 hour'::interval, timec), avg(temperature) +FROM conditions +GROUP BY 1 +WITH NO DATA; +ERROR: time bucket width must be greater than zero +CREATE MATERIALIZED VIEW mat_zero WITH (timescaledb.continuous) +AS +SELECT time_bucket('0'::interval, timec), avg(temperature) +FROM conditions +GROUP BY 1 +WITH NO DATA; +ERROR: time bucket width must be greater than zero +CREATE MATERIALIZED VIEW mat_neg_month WITH (timescaledb.continuous) +AS +SELECT time_bucket('-1 month'::interval, timec), avg(temperature) +FROM conditions +GROUP BY 1 +WITH NO DATA; +ERROR: time bucket width must be greater than zero -- row security on table create table rowsec_tab( a bigint, b integer, c integer); select table_name from create_hypertable( 'rowsec_tab', 'a', chunk_time_interval=>10); @@ -594,3 +617,30 @@ ERROR: invalid continuous aggregate view -- No FROM clause in CAGG definition CREATE MATERIALIZED VIEW cagg1 with (timescaledb.continuous, timescaledb.materialized_only=false) AS SELECT 1 GROUP BY 1 WITH NO DATA; ERROR: invalid continuous aggregate query +-- non-positive bucket width on integer-typed hypertable +CREATE TABLE int_ht(timec bigint NOT NULL, val float); +SELECT create_hypertable('int_ht', 'timec', chunk_time_interval => 1000000); + create_hypertable +---------------------- + (19,public,int_ht,t) + +CREATE OR REPLACE FUNCTION int_ht_now() RETURNS bigint LANGUAGE SQL STABLE AS $$ SELECT 0::bigint $$; +SELECT set_integer_now_func('int_ht', 'int_ht_now'); + set_integer_now_func +---------------------- + + +CREATE MATERIALIZED VIEW mat_neg_int WITH (timescaledb.continuous) +AS +SELECT time_bucket(-100::bigint, timec), avg(val) +FROM int_ht +GROUP BY 1 +WITH NO DATA; +ERROR: time bucket width must be greater than zero +CREATE MATERIALIZED VIEW mat_zero_int WITH (timescaledb.continuous) +AS +SELECT time_bucket(0::bigint, timec), avg(val) +FROM int_ht +GROUP BY 1 +WITH NO DATA; +ERROR: time bucket width must be greater than zero diff --git a/tsl/test/sql/cagg_errors.sql b/tsl/test/sql/cagg_errors.sql index 61e5b2cccd0..7f75dc1bce8 100644 --- a/tsl/test/sql/cagg_errors.sql +++ b/tsl/test/sql/cagg_errors.sql @@ -209,6 +209,29 @@ FROM conditions GROUP BY 1 WITH NO DATA; +-- negative or zero bucket width must be rejected at creation time; +-- otherwise refresh later trips Assert(bucket_width > 0). +CREATE MATERIALIZED VIEW mat_neg WITH (timescaledb.continuous) +AS +SELECT time_bucket('-1 hour'::interval, timec), avg(temperature) +FROM conditions +GROUP BY 1 +WITH NO DATA; + +CREATE MATERIALIZED VIEW mat_zero WITH (timescaledb.continuous) +AS +SELECT time_bucket('0'::interval, timec), avg(temperature) +FROM conditions +GROUP BY 1 +WITH NO DATA; + +CREATE MATERIALIZED VIEW mat_neg_month WITH (timescaledb.continuous) +AS +SELECT time_bucket('-1 month'::interval, timec), avg(temperature) +FROM conditions +GROUP BY 1 +WITH NO DATA; + -- row security on table create table rowsec_tab( a bigint, b integer, c integer); select table_name from create_hypertable( 'rowsec_tab', 'a', chunk_time_interval=>10); @@ -504,3 +527,23 @@ CREATE MATERIALIZED VIEW cagg1 WITH (timescaledb.continuous, timescaledb.materia -- No FROM clause in CAGG definition CREATE MATERIALIZED VIEW cagg1 with (timescaledb.continuous, timescaledb.materialized_only=false) AS SELECT 1 GROUP BY 1 WITH NO DATA; + +-- non-positive bucket width on integer-typed hypertable +CREATE TABLE int_ht(timec bigint NOT NULL, val float); +SELECT create_hypertable('int_ht', 'timec', chunk_time_interval => 1000000); +CREATE OR REPLACE FUNCTION int_ht_now() RETURNS bigint LANGUAGE SQL STABLE AS $$ SELECT 0::bigint $$; +SELECT set_integer_now_func('int_ht', 'int_ht_now'); + +CREATE MATERIALIZED VIEW mat_neg_int WITH (timescaledb.continuous) +AS +SELECT time_bucket(-100::bigint, timec), avg(val) +FROM int_ht +GROUP BY 1 +WITH NO DATA; + +CREATE MATERIALIZED VIEW mat_zero_int WITH (timescaledb.continuous) +AS +SELECT time_bucket(0::bigint, timec), avg(val) +FROM int_ht +GROUP BY 1 +WITH NO DATA;