From a22c01540cf1c4bb7df81d63edab5ee3bbdc1571 Mon Sep 17 00:00:00 2001 From: Jan Nidzwetzki Date: Fri, 6 Oct 2023 20:51:01 +0200 Subject: [PATCH] Handle non existing ht in cache_inval_entry_init When the continuous_agg_invalidation trigger is called with an invalid hypertable id (e.g., caused by an inconsistent backup restore), the hypertable lookup returns NULL. This case was not handled properly so far. This patch adds proper checks to the function. (cherry picked from commit 7dc14ac2ed51e05e9ac33ac76143f0f28e4168e6) --- tsl/src/continuous_aggs/insert.c | 7 +++++++ tsl/test/expected/cagg_usage.out | 14 ++++++++++++++ tsl/test/sql/cagg_usage.sql | 12 ++++++++++++ 3 files changed, 33 insertions(+) diff --git a/tsl/src/continuous_aggs/insert.c b/tsl/src/continuous_aggs/insert.c index e96c47d4336..8b31bf93f35 100644 --- a/tsl/src/continuous_aggs/insert.c +++ b/tsl/src/continuous_aggs/insert.c @@ -155,6 +155,13 @@ cache_inval_entry_init(ContinuousAggsCacheInvalEntry *cache_entry, int32 hyperta /* NOTE: we can remove the id=>relid scan, if it becomes an issue, by getting the * hypertable_relid directly from the Chunk*/ Hypertable *ht = ts_hypertable_cache_get_entry_by_id(ht_cache, hypertable_id); + if (ht == NULL) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unable to determine relid for hypertable %d", hypertable_id))); + } + cache_entry->hypertable_id = hypertable_id; cache_entry->entry_id = entry_id; cache_entry->hypertable_relid = ht->main_table_relid; diff --git a/tsl/test/expected/cagg_usage.out b/tsl/test/expected/cagg_usage.out index 4d67ff9a2ef..4b265c0c794 100644 --- a/tsl/test/expected/cagg_usage.out +++ b/tsl/test/expected/cagg_usage.out @@ -412,6 +412,20 @@ DROP TABLE whatever; -- Check that continuous_agg_invalidation_trigger() handles no arguments properly SELECT _timescaledb_functions.continuous_agg_invalidation_trigger(); ERROR: must supply hypertable id +-- Check that continuous_agg_invalidation_trigger() not crashes when an invalid ht id is used +CREATE TABLE sensor_data ( +time timestamptz NOT NULL, +sensor_id integer NOT NULL, +cpu double precision NULL, +temperature double precision NULL); +SELECT FROM create_hypertable('sensor_data','time'); +-- +(1 row) + +CREATE TRIGGER ts_cagg_invalidation_trigger AFTER INSERT OR DELETE OR UPDATE ON sensor_data FOR EACH ROW EXECUTE FUNCTION _timescaledb_functions.continuous_agg_invalidation_trigger(999999); +INSERT INTO sensor_data values('1980-01-01 00:00:00-00', 1, 1, 1); +ERROR: unable to determine relid for hypertable 999999 +DROP TABLE sensor_data; -- END OF BASIC USAGE TESTS -- CREATE TABLE metrics(time timestamptz, device TEXT, value float); SELECT table_name FROM create_hypertable('metrics','time'); diff --git a/tsl/test/sql/cagg_usage.sql b/tsl/test/sql/cagg_usage.sql index 29ae3e9a567..0e87b5bee56 100644 --- a/tsl/test/sql/cagg_usage.sql +++ b/tsl/test/sql/cagg_usage.sql @@ -270,6 +270,18 @@ DROP TABLE whatever; -- Check that continuous_agg_invalidation_trigger() handles no arguments properly SELECT _timescaledb_functions.continuous_agg_invalidation_trigger(); +-- Check that continuous_agg_invalidation_trigger() not crashes when an invalid ht id is used +CREATE TABLE sensor_data ( +time timestamptz NOT NULL, +sensor_id integer NOT NULL, +cpu double precision NULL, +temperature double precision NULL); + +SELECT FROM create_hypertable('sensor_data','time'); +CREATE TRIGGER ts_cagg_invalidation_trigger AFTER INSERT OR DELETE OR UPDATE ON sensor_data FOR EACH ROW EXECUTE FUNCTION _timescaledb_functions.continuous_agg_invalidation_trigger(999999); +INSERT INTO sensor_data values('1980-01-01 00:00:00-00', 1, 1, 1); +DROP TABLE sensor_data; + -- END OF BASIC USAGE TESTS -- CREATE TABLE metrics(time timestamptz, device TEXT, value float);