From 5ed25ac61842520b73b1532bc1e07afef6cf250b Mon Sep 17 00:00:00 2001 From: Rafia Sabih Date: Wed, 8 Feb 2023 11:54:28 +0100 Subject: [PATCH] Enable joins for heirarchical continuous aggregates The joins could be between a continuous aggregate and hypertable, continuous aggregate and a regular Postgres table, and continuous aggregate and a regular Postgres view. --- CHANGELOG.md | 6 +- tsl/src/continuous_aggs/create.c | 65 +- tsl/test/expected/cagg_joins-12.out | 40 +- tsl/test/expected/cagg_joins-13.out | 40 +- tsl/test/expected/cagg_joins-14.out | 40 +- tsl/test/expected/cagg_joins-15.out | 40 +- tsl/test/expected/cagg_on_cagg.out | 1145 ++--- tsl/test/expected/cagg_on_cagg_joins.out | 4423 ++++++++++++++++++ tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/cagg_joins.sql.in | 16 +- tsl/test/sql/cagg_on_cagg.sql | 2 +- tsl/test/sql/cagg_on_cagg_joins.sql | 288 ++ tsl/test/sql/include/cagg_on_cagg_common.sql | 44 +- tsl/test/sql/include/cagg_on_cagg_setup.sql | 29 +- 14 files changed, 5538 insertions(+), 641 deletions(-) create mode 100644 tsl/test/expected/cagg_on_cagg_joins.out create mode 100644 tsl/test/sql/cagg_on_cagg_joins.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index e89e51ed943..29b1f1a51f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ accidentally triggering the load of a previous DB version.** * #5361 Add parallel support for partialize_agg() * #5252 Improve unique constraint support on compressed hypertables * #5312 Add timeout support to ping_data_node() +* #5384 Fix Hierarchical Continuous Aggregates chunk_interval_size **Bugfixes** * #5396 Fix SEGMENTBY columns predicates to be pushed down @@ -41,7 +42,6 @@ We recommend that you upgrade at the next available opportunity. * #5364 Fix num_chunks inconsistency in hypertables view * #5367 Fix column name handling in old-style continuous aggregates * #5378 Fix multinode DML HA performance regression -* #5384 Fix Hierarchical Continuous Aggregates chunk_interval_size * #5304 Fix sub-second intervals in hierarchical caggs **Thanks** @@ -76,6 +76,10 @@ Sooner to that time, we will announce the specific version of TimescaleDB in whi * #5246 Make connection establishment interruptible * #5253 Make data node command execution interruptible * #5262 Extend enabling compression on a continuous aggregrate with 'compress_segmentby' and 'compress_orderby' parameters +* #5343 Set PortalContext when starting job +* #5312 Add timeout support to the ping_data_node() +* #5212 Allow pushdown of reference table joins +* #5344 Enable JOINS for Hierarchical continuous aggregates **Bugfixes** * #5214 Fix use of prepared statement in async module diff --git a/tsl/src/continuous_aggs/create.c b/tsl/src/continuous_aggs/create.c index b3d6b3c774a..de1d0d21ded 100644 --- a/tsl/src/continuous_aggs/create.c +++ b/tsl/src/continuous_aggs/create.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1283,31 +1284,34 @@ cagg_validate_query(const Query *query, const bool finalized, const char *cagg_s op = (OpExpr *) join->quals; rte = list_nth(query->rtable, ((RangeTblRef *) join->larg)->rtindex - 1); rte_other = list_nth(query->rtable, ((RangeTblRef *) join->rarg)->rtindex - 1); + if (rte->subquery != NULL || rte_other->subquery != NULL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("invalid continuous aggregate view"), + errdetail("sub-queries are not supported in FROM clause"))); + RangeTblEntry *jrte = rt_fetch(join->rtindex, query->rtable); + if (jrte->joinaliasvars == NIL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("invalid continuous aggregate view"))); } } } - /* - * Cagg with joins does not support hierarchical caggs in from clause. - */ - if (rte->relkind == RELKIND_VIEW || rte_other->relkind == RELKIND_VIEW) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("joins for hierarchical continuous aggregates are not supported"))); - /* * Error out if there is aynthing else than one normal table and one hypertable - * in the from clause, e.g. sub-query. + * in the from clause, e.g. sub-query, lateral, two hypertables, etc. */ - if (((rte->relkind != RELKIND_RELATION && rte->relkind != RELKIND_VIEW) || - rte->tablesample || rte->inh == false) || - ((rte_other->relkind != RELKIND_RELATION && rte_other->relkind != RELKIND_VIEW) || - rte_other->tablesample || rte_other->inh == false) || - (ts_is_hypertable(rte->relid) == ts_is_hypertable(rte_other->relid))) + if (rte->lateral || rte_other->lateral || + (rte->relkind == RELKIND_VIEW && ts_is_hypertable(rte_other->relid)) || + (rte_other->relkind == RELKIND_VIEW && ts_is_hypertable(rte->relid)) || + (rte->relkind != RELKIND_VIEW && rte_other->relkind != RELKIND_VIEW && + (ts_is_hypertable(rte->relid) == ts_is_hypertable(rte_other->relid)))) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("invalid continuous aggregate view"), - errdetail("from clause can only have one hypertable and one normal table"))); + errdetail("views, lateral, multiple hypertables or normal tables" + " are not supported in FROM clause"))); /* Only inner joins are allowed. */ if (jointype != JOIN_INNER) @@ -1339,7 +1343,12 @@ cagg_validate_query(const Query *query, const bool finalized, const char *cagg_s * that we know which one is hypertable to carry out the related * processing in later parts of code. */ - normal_table_id = ts_is_hypertable(rte->relid) ? rte_other->relid : rte->relid; + if (rte->relkind == RELKIND_VIEW) + normal_table_id = rte_other->relid; + else if (rte_other->relkind == RELKIND_VIEW) + normal_table_id = rte->relid; + else + normal_table_id = ts_is_hypertable(rte->relid) ? rte_other->relid : rte->relid; if (normal_table_id == rte->relid) rte = rte_other; } @@ -2449,7 +2458,8 @@ finalizequery_get_select_query(FinalizeQueryInfo *inp, List *matcollist, * which contains the information of the materialised hypertable * that is created for this cagg. */ - if (list_length(inp->final_userquery->jointree->fromlist) >= CONTINUOUS_AGG_MAX_JOIN_RELATIONS) + if (list_length(inp->final_userquery->jointree->fromlist) >= CONTINUOUS_AGG_MAX_JOIN_RELATIONS || + !IsA(linitial(inp->final_userquery->jointree->fromlist), RangeTblRef)) { rte = makeNode(RangeTblEntry); rte->alias = makeAlias(relname, NIL); @@ -2457,6 +2467,18 @@ finalizequery_get_select_query(FinalizeQueryInfo *inp, List *matcollist, rte->inh = true; rte->rellockmode = 1; rte->eref = copyObject(rte->alias); + ListCell *l; + foreach (l, inp->final_userquery->jointree->fromlist) + { + Node *jtnode = (Node *) lfirst(l); + JoinExpr *join = NULL; + if (IsA(jtnode, JoinExpr)) + { + join = castNode(JoinExpr, jtnode); + RangeTblEntry *jrte = rt_fetch(join->rtindex, inp->final_userquery->rtable); + rte->joinaliasvars = jrte->joinaliasvars; + } + } } else rte = llast_node(RangeTblEntry, inp->final_userquery->rtable); @@ -3387,12 +3409,17 @@ build_union_query(CAggTimebucketInfo *tbinfo, int matpartcolno, Query *q1, Query */ if (list_length(q2->rtable) == CONTINUOUS_AGG_MAX_JOIN_RELATIONS) { + Oid normal_table_id = InvalidOid; RangeTblRef *rtref = linitial_node(RangeTblRef, q2->jointree->fromlist); RangeTblEntry *rte = list_nth(q2->rtable, rtref->rtindex - 1); RangeTblRef *rtref_other = lsecond_node(RangeTblRef, q2->jointree->fromlist); RangeTblEntry *rte_other = list_nth(q2->rtable, rtref_other->rtindex - 1); - - Oid normal_table_id = ts_is_hypertable(rte->relid) ? rte_other->relid : rte->relid; + if (rte->relkind == RELKIND_VIEW) + normal_table_id = rte_other->relid; + else if (rte_other->relkind == RELKIND_VIEW) + normal_table_id = rte->relid; + else + normal_table_id = ts_is_hypertable(rte->relid) ? rte_other->relid : rte->relid; if (normal_table_id == rte->relid) varno = 2; else diff --git a/tsl/test/expected/cagg_joins-12.out b/tsl/test/expected/cagg_joins-12.out index a9954e1b047..0a0a25c5c0e 100644 --- a/tsl/test/expected/cagg_joins-12.out +++ b/tsl/test/expected/cagg_joins-12.out @@ -193,10 +193,11 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, AVG(temperature), MAX(temperature), MIN(temperature), - name + name, + devices.device_id AS thermo_id FROM conditions, devices WHERE conditions.device_id = devices.device_id -GROUP BY name, bucket; +GROUP BY name, bucket, thermo_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. CREATE MATERIALIZED VIEW conditions_summary_daily_reorder @@ -297,7 +298,7 @@ select temperature, count(*) from conditions, LATERAL (Select * from mat_t1 where a = conditions.temperature) q group by temperature WITH NO DATA; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out if from clause has view CREATE MATERIALIZED VIEW conditions_summary_daily_view WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -310,13 +311,15 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions, devices_view WHERE conditions.device_id = devices_view.device_id GROUP BY name, bucket, devices_view.device_id; -ERROR: joins for hierarchical continuous aggregates are not supported +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause -- Nested CAgg over a CAgg with join CREATE MATERIALIZED VIEW cagg_on_cagg WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(INTERVAL '1 day', bucket) AS bucket, SUM(avg) AS temperature -FROM conditions_summary_daily +FROM conditions_summary_daily, devices +WHERE devices.device_id = conditions_summary_daily.thermo_id GROUP BY 1; NOTICE: refreshing continuous aggregate "cagg_on_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. @@ -337,7 +340,7 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions JOIN (SELECT * FROM devices WHERE location in (SELECT name from cities where currency = 'EUR')) dev ON conditions.device_id = dev.device_id GROUP BY name, bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: sub-queries are not supported in FROM clause DROP TABLE cities CASCADE; --Error out when join is between two hypertables CREATE MATERIALIZED VIEW conditions_summary_daily_ht @@ -350,7 +353,7 @@ FROM conditions, conditions_dup WHERE conditions.device_id = conditions_dup.device_id GROUP BY bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is between two normal tables CREATE MATERIALIZED VIEW conditions_summary_daily_nt WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -363,7 +366,7 @@ FROM devices, devices_dup WHERE devices.device_id = devices_dup.device_id GROUP BY devices.name, devices.location; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is on non-equality condition CREATE MATERIALIZED VIEW conditions_summary_daily_unequal WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -432,25 +435,27 @@ WHERE conditions.device_id = devices.device_id GROUP BY name, bucket, devices.device_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. ---Errors out for join between cagg and normal table +--Join between cagg and normal table CREATE MATERIALIZED VIEW conditions_summary_daily_nested WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, devices.name FROM conditions_summary_daily_cagg cagg, devices WHERE cagg.device_id = devices.device_id -GROUP BY devices.name, bucket; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2; +NOTICE: refreshing continuous aggregate "conditions_summary_daily_nested" +HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. --Error out for join between cagg and hypertable -CREATE MATERIALIZED VIEW conditions_summary_daily_nested +CREATE MATERIALIZED VIEW conditions_summary_daily_nested_ht WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, cagg.name, conditions.temperature FROM conditions_summary_daily_cagg cagg, conditions WHERE cagg.device_id = conditions.device_id -GROUP BY conditions.temperature, bucket, cagg.name; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2,3; +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause \set VERBOSITY terse DROP TABLE conditions CASCADE; NOTICE: drop cascades to 15 other objects @@ -459,8 +464,11 @@ NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to 2 other objects +ERROR: cannot drop view conditions_summary_daily_cagg because other objects depend on it DROP TABLE devices CASCADE; -NOTICE: drop cascades to view devices_view +NOTICE: drop cascades to 18 other objects +NOTICE: drop cascades to 2 other objects +NOTICE: drop cascades to 2 other objects +ERROR: cannot drop the partial/direct view because it is required by a continuous aggregate DROP TABLE conditions_dup CASCADE; DROP TABLE devices_dup CASCADE; diff --git a/tsl/test/expected/cagg_joins-13.out b/tsl/test/expected/cagg_joins-13.out index f1f386dd1b9..651ebe26345 100644 --- a/tsl/test/expected/cagg_joins-13.out +++ b/tsl/test/expected/cagg_joins-13.out @@ -193,10 +193,11 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, AVG(temperature), MAX(temperature), MIN(temperature), - name + name, + devices.device_id AS thermo_id FROM conditions, devices WHERE conditions.device_id = devices.device_id -GROUP BY name, bucket; +GROUP BY name, bucket, thermo_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. CREATE MATERIALIZED VIEW conditions_summary_daily_reorder @@ -298,7 +299,7 @@ select temperature, count(*) from conditions, LATERAL (Select * from mat_t1 where a = conditions.temperature) q group by temperature WITH NO DATA; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out if from clause has view CREATE MATERIALIZED VIEW conditions_summary_daily_view WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -311,13 +312,15 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions, devices_view WHERE conditions.device_id = devices_view.device_id GROUP BY name, bucket, devices_view.device_id; -ERROR: joins for hierarchical continuous aggregates are not supported +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause -- Nested CAgg over a CAgg with join CREATE MATERIALIZED VIEW cagg_on_cagg WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(INTERVAL '1 day', bucket) AS bucket, SUM(avg) AS temperature -FROM conditions_summary_daily +FROM conditions_summary_daily, devices +WHERE devices.device_id = conditions_summary_daily.thermo_id GROUP BY 1; NOTICE: refreshing continuous aggregate "cagg_on_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. @@ -338,7 +341,7 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions JOIN (SELECT * FROM devices WHERE location in (SELECT name from cities where currency = 'EUR')) dev ON conditions.device_id = dev.device_id GROUP BY name, bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: sub-queries are not supported in FROM clause DROP TABLE cities CASCADE; --Error out when join is between two hypertables CREATE MATERIALIZED VIEW conditions_summary_daily_ht @@ -351,7 +354,7 @@ FROM conditions, conditions_dup WHERE conditions.device_id = conditions_dup.device_id GROUP BY bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is between two normal tables CREATE MATERIALIZED VIEW conditions_summary_daily_nt WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -364,7 +367,7 @@ FROM devices, devices_dup WHERE devices.device_id = devices_dup.device_id GROUP BY devices.name, devices.location; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is on non-equality condition CREATE MATERIALIZED VIEW conditions_summary_daily_unequal WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -433,25 +436,27 @@ WHERE conditions.device_id = devices.device_id GROUP BY name, bucket, devices.device_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. ---Errors out for join between cagg and normal table +--Join between cagg and normal table CREATE MATERIALIZED VIEW conditions_summary_daily_nested WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, devices.name FROM conditions_summary_daily_cagg cagg, devices WHERE cagg.device_id = devices.device_id -GROUP BY devices.name, bucket; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2; +NOTICE: refreshing continuous aggregate "conditions_summary_daily_nested" +HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. --Error out for join between cagg and hypertable -CREATE MATERIALIZED VIEW conditions_summary_daily_nested +CREATE MATERIALIZED VIEW conditions_summary_daily_nested_ht WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, cagg.name, conditions.temperature FROM conditions_summary_daily_cagg cagg, conditions WHERE cagg.device_id = conditions.device_id -GROUP BY conditions.temperature, bucket, cagg.name; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2,3; +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause \set VERBOSITY terse DROP TABLE conditions CASCADE; NOTICE: drop cascades to 24 other objects @@ -463,8 +468,11 @@ NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to 2 other objects +ERROR: cannot drop view conditions_summary_daily_cagg because other objects depend on it DROP TABLE devices CASCADE; -NOTICE: drop cascades to view devices_view +NOTICE: drop cascades to 27 other objects +NOTICE: drop cascades to 2 other objects +NOTICE: drop cascades to 2 other objects +ERROR: cannot drop the partial/direct view because it is required by a continuous aggregate DROP TABLE conditions_dup CASCADE; DROP TABLE devices_dup CASCADE; diff --git a/tsl/test/expected/cagg_joins-14.out b/tsl/test/expected/cagg_joins-14.out index f1f386dd1b9..651ebe26345 100644 --- a/tsl/test/expected/cagg_joins-14.out +++ b/tsl/test/expected/cagg_joins-14.out @@ -193,10 +193,11 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, AVG(temperature), MAX(temperature), MIN(temperature), - name + name, + devices.device_id AS thermo_id FROM conditions, devices WHERE conditions.device_id = devices.device_id -GROUP BY name, bucket; +GROUP BY name, bucket, thermo_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. CREATE MATERIALIZED VIEW conditions_summary_daily_reorder @@ -298,7 +299,7 @@ select temperature, count(*) from conditions, LATERAL (Select * from mat_t1 where a = conditions.temperature) q group by temperature WITH NO DATA; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out if from clause has view CREATE MATERIALIZED VIEW conditions_summary_daily_view WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -311,13 +312,15 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions, devices_view WHERE conditions.device_id = devices_view.device_id GROUP BY name, bucket, devices_view.device_id; -ERROR: joins for hierarchical continuous aggregates are not supported +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause -- Nested CAgg over a CAgg with join CREATE MATERIALIZED VIEW cagg_on_cagg WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(INTERVAL '1 day', bucket) AS bucket, SUM(avg) AS temperature -FROM conditions_summary_daily +FROM conditions_summary_daily, devices +WHERE devices.device_id = conditions_summary_daily.thermo_id GROUP BY 1; NOTICE: refreshing continuous aggregate "cagg_on_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. @@ -338,7 +341,7 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions JOIN (SELECT * FROM devices WHERE location in (SELECT name from cities where currency = 'EUR')) dev ON conditions.device_id = dev.device_id GROUP BY name, bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: sub-queries are not supported in FROM clause DROP TABLE cities CASCADE; --Error out when join is between two hypertables CREATE MATERIALIZED VIEW conditions_summary_daily_ht @@ -351,7 +354,7 @@ FROM conditions, conditions_dup WHERE conditions.device_id = conditions_dup.device_id GROUP BY bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is between two normal tables CREATE MATERIALIZED VIEW conditions_summary_daily_nt WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -364,7 +367,7 @@ FROM devices, devices_dup WHERE devices.device_id = devices_dup.device_id GROUP BY devices.name, devices.location; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is on non-equality condition CREATE MATERIALIZED VIEW conditions_summary_daily_unequal WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -433,25 +436,27 @@ WHERE conditions.device_id = devices.device_id GROUP BY name, bucket, devices.device_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. ---Errors out for join between cagg and normal table +--Join between cagg and normal table CREATE MATERIALIZED VIEW conditions_summary_daily_nested WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, devices.name FROM conditions_summary_daily_cagg cagg, devices WHERE cagg.device_id = devices.device_id -GROUP BY devices.name, bucket; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2; +NOTICE: refreshing continuous aggregate "conditions_summary_daily_nested" +HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. --Error out for join between cagg and hypertable -CREATE MATERIALIZED VIEW conditions_summary_daily_nested +CREATE MATERIALIZED VIEW conditions_summary_daily_nested_ht WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, cagg.name, conditions.temperature FROM conditions_summary_daily_cagg cagg, conditions WHERE cagg.device_id = conditions.device_id -GROUP BY conditions.temperature, bucket, cagg.name; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2,3; +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause \set VERBOSITY terse DROP TABLE conditions CASCADE; NOTICE: drop cascades to 24 other objects @@ -463,8 +468,11 @@ NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to 2 other objects +ERROR: cannot drop view conditions_summary_daily_cagg because other objects depend on it DROP TABLE devices CASCADE; -NOTICE: drop cascades to view devices_view +NOTICE: drop cascades to 27 other objects +NOTICE: drop cascades to 2 other objects +NOTICE: drop cascades to 2 other objects +ERROR: cannot drop the partial/direct view because it is required by a continuous aggregate DROP TABLE conditions_dup CASCADE; DROP TABLE devices_dup CASCADE; diff --git a/tsl/test/expected/cagg_joins-15.out b/tsl/test/expected/cagg_joins-15.out index f1f386dd1b9..651ebe26345 100644 --- a/tsl/test/expected/cagg_joins-15.out +++ b/tsl/test/expected/cagg_joins-15.out @@ -193,10 +193,11 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, AVG(temperature), MAX(temperature), MIN(temperature), - name + name, + devices.device_id AS thermo_id FROM conditions, devices WHERE conditions.device_id = devices.device_id -GROUP BY name, bucket; +GROUP BY name, bucket, thermo_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. CREATE MATERIALIZED VIEW conditions_summary_daily_reorder @@ -298,7 +299,7 @@ select temperature, count(*) from conditions, LATERAL (Select * from mat_t1 where a = conditions.temperature) q group by temperature WITH NO DATA; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out if from clause has view CREATE MATERIALIZED VIEW conditions_summary_daily_view WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -311,13 +312,15 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions, devices_view WHERE conditions.device_id = devices_view.device_id GROUP BY name, bucket, devices_view.device_id; -ERROR: joins for hierarchical continuous aggregates are not supported +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause -- Nested CAgg over a CAgg with join CREATE MATERIALIZED VIEW cagg_on_cagg WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(INTERVAL '1 day', bucket) AS bucket, SUM(avg) AS temperature -FROM conditions_summary_daily +FROM conditions_summary_daily, devices +WHERE devices.device_id = conditions_summary_daily.thermo_id GROUP BY 1; NOTICE: refreshing continuous aggregate "cagg_on_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. @@ -338,7 +341,7 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, FROM conditions JOIN (SELECT * FROM devices WHERE location in (SELECT name from cities where currency = 'EUR')) dev ON conditions.device_id = dev.device_id GROUP BY name, bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: sub-queries are not supported in FROM clause DROP TABLE cities CASCADE; --Error out when join is between two hypertables CREATE MATERIALIZED VIEW conditions_summary_daily_ht @@ -351,7 +354,7 @@ FROM conditions, conditions_dup WHERE conditions.device_id = conditions_dup.device_id GROUP BY bucket; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is between two normal tables CREATE MATERIALIZED VIEW conditions_summary_daily_nt WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -364,7 +367,7 @@ FROM devices, devices_dup WHERE devices.device_id = devices_dup.device_id GROUP BY devices.name, devices.location; ERROR: invalid continuous aggregate view -DETAIL: from clause can only have one hypertable and one normal table +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause --Error out when join is on non-equality condition CREATE MATERIALIZED VIEW conditions_summary_daily_unequal WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -433,25 +436,27 @@ WHERE conditions.device_id = devices.device_id GROUP BY name, bucket, devices.device_id; NOTICE: refreshing continuous aggregate "conditions_summary_daily_cagg" HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. ---Errors out for join between cagg and normal table +--Join between cagg and normal table CREATE MATERIALIZED VIEW conditions_summary_daily_nested WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, devices.name FROM conditions_summary_daily_cagg cagg, devices WHERE cagg.device_id = devices.device_id -GROUP BY devices.name, bucket; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2; +NOTICE: refreshing continuous aggregate "conditions_summary_daily_nested" +HINT: Use WITH NO DATA if you do not want to refresh the continuous aggregate on creation. --Error out for join between cagg and hypertable -CREATE MATERIALIZED VIEW conditions_summary_daily_nested +CREATE MATERIALIZED VIEW conditions_summary_daily_nested_ht WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, cagg.name, conditions.temperature FROM conditions_summary_daily_cagg cagg, conditions WHERE cagg.device_id = conditions.device_id -GROUP BY conditions.temperature, bucket, cagg.name; -ERROR: joins for hierarchical continuous aggregates are not supported +GROUP BY 1,2,3; +ERROR: invalid continuous aggregate view +DETAIL: views, lateral, multiple hypertables or normal tables are not supported in FROM clause \set VERBOSITY terse DROP TABLE conditions CASCADE; NOTICE: drop cascades to 24 other objects @@ -463,8 +468,11 @@ NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to 2 other objects +ERROR: cannot drop view conditions_summary_daily_cagg because other objects depend on it DROP TABLE devices CASCADE; -NOTICE: drop cascades to view devices_view +NOTICE: drop cascades to 27 other objects +NOTICE: drop cascades to 2 other objects +NOTICE: drop cascades to 2 other objects +ERROR: cannot drop the partial/direct view because it is required by a continuous aggregate DROP TABLE conditions_dup CASCADE; DROP TABLE devices_dup CASCADE; diff --git a/tsl/test/expected/cagg_on_cagg.out b/tsl/test/expected/cagg_on_cagg.out index e5059774cb7..0996edcaa09 100644 --- a/tsl/test/expected/cagg_on_cagg.out +++ b/tsl/test/expected/cagg_on_cagg.out @@ -5,6 +5,7 @@ \set IS_DISTRIBUTED FALSE \set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE \set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE +\set IS_JOIN FALSE -- ######################################################## -- ## INTEGER data type tests -- ######################################################## @@ -37,16 +38,23 @@ SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exist, skipping \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -66,9 +74,9 @@ psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exi \endif \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -88,9 +96,9 @@ psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exi (1 row) - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif \ir include/cagg_on_cagg_common.sql -- This file and its contents are licensed under the Timescale License. @@ -101,9 +109,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL @@ -111,18 +120,32 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval @@ -157,8 +180,8 @@ WITH NO DATA; \endif -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- + bucket | temperature | device_id +--------+-------------+----------- (0 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -166,22 +189,18 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; --------+------------- (0 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -191,12 +210,7 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; 5 | 20 (2 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 -(1 row) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); @@ -207,11 +221,11 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- Materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -240,11 +254,11 @@ INSERT INTO conditions ("time", temperature) VALUES (10, 2); \endif -- No changes SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -266,12 +280,12 @@ ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only= ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime changes, just new region SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 - 10 | 2 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | (4 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -299,13 +313,14 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- All changes are materialized SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 7 - 5 | 20 - 10 | 2 -(4 rows) + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -360,21 +375,21 @@ SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; \set ON_ERROR_STOP 0 -- should error because it depends of other CAGGs DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:150: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:151: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:152: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:153: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date \set ON_ERROR_STOP 1 -- DROP the 3TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:157: NOTICE: drop cascades to table _timescaledb_internal._hyper_4_4_chunk +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_4_4_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:160: ERROR: relation "conditions_summary_3_10" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs @@ -382,13 +397,14 @@ TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 7 - 5 | 20 - 10 | 2 -(4 rows) + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -397,30 +413,31 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -- DROP the 2TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:171: NOTICE: drop cascades to table _timescaledb_internal._hyper_3_3_chunk +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_3_3_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:174: ERROR: relation "conditions_summary_2_5" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 7 - 5 | 20 - 10 | 2 -(4 rows) + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) -- DROP the first CAGG should work DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:181: NOTICE: drop cascades to table _timescaledb_internal._hyper_2_2_chunk +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_2_2_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:184: ERROR: relation "conditions_summary_1_1" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 \set ON_ERROR_STOP 1 -- Default tests \set IS_DEFAULT_COLUMN_ORDER TRUE @@ -438,16 +455,23 @@ Running local hypertable tests SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -467,9 +491,9 @@ DROP TABLE IF EXISTS conditions CASCADE; \endif \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -489,9 +513,9 @@ DROP TABLE IF EXISTS conditions CASCADE; (1 row) - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif \ir include/cagg_on_cagg_common.sql -- This file and its contents are licensed under the Timescale License. @@ -502,9 +526,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL @@ -512,18 +537,32 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval @@ -558,8 +597,8 @@ WITH NO DATA; \endif -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- + bucket | temperature | device_id +--------+-------------+----------- (0 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -567,22 +606,18 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; --------+------------- (0 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -592,12 +627,7 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; 5 | 20 (2 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 -(1 row) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); @@ -608,11 +638,11 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- Materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -641,11 +671,11 @@ INSERT INTO conditions ("time", temperature) VALUES (10, 2); \endif -- No changes SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -667,12 +697,12 @@ ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only= ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime changes, just new region SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 5 - 5 | 20 - 10 | 2 + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | (4 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -700,13 +730,14 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- All changes are materialized SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 7 - 5 | 20 - 10 | 2 -(4 rows) + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -761,21 +792,21 @@ SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; \set ON_ERROR_STOP 0 -- should error because it depends of other CAGGs DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:150: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:151: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:152: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:153: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date \set ON_ERROR_STOP 1 -- DROP the 3TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:157: NOTICE: drop cascades to table _timescaledb_internal._hyper_8_9_chunk +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_8_9_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:160: ERROR: relation "conditions_summary_3_10" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs @@ -783,13 +814,14 @@ TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 7 - 5 | 20 - 10 | 2 -(4 rows) + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -798,30 +830,31 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -- DROP the 2TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:171: NOTICE: drop cascades to table _timescaledb_internal._hyper_7_8_chunk +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_7_8_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:174: ERROR: relation "conditions_summary_2_5" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 1 | 10 - 2 | 7 - 5 | 20 - 10 | 2 -(4 rows) + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) -- DROP the first CAGG should work DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:181: NOTICE: drop cascades to table _timescaledb_internal._hyper_6_7_chunk +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_6_7_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:184: ERROR: relation "conditions_summary_1_1" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 \set ON_ERROR_STOP 1 -- -- Validation test for non-multiple bucket sizes @@ -1094,16 +1127,23 @@ Running local hypertable tests SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -1113,7 +1153,7 @@ DROP TABLE IF EXISTS conditions CASCADE; \else \if :IS_TIME_DIMENSION SELECT table_name FROM create_hypertable('conditions', 'time'); -psql:include/cagg_on_cagg_setup.sql:35: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices +psql:include/cagg_on_cagg_setup.sql:43: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices table_name ------------ conditions @@ -1124,9 +1164,9 @@ psql:include/cagg_on_cagg_setup.sql:35: WARNING: column type "timestamp without \endif \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -1141,9 +1181,9 @@ psql:include/cagg_on_cagg_setup.sql:35: WARNING: column type "timestamp without CALL distributed_exec (:'STMT'); \endif SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif \ir include/cagg_on_cagg_common.sql -- This file and its contents are licensed under the Timescale License. @@ -1154,9 +1194,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL @@ -1164,18 +1205,32 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval @@ -1210,8 +1265,8 @@ WITH NO DATA; \endif -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- + bucket | temperature | device_id +--------+-------------+----------- (0 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1219,22 +1274,18 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; --------+------------- (0 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1244,12 +1295,7 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; Sun Jan 02 00:00:00 2022 | 20 (2 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 -(1 row) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); @@ -1260,11 +1306,11 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- Materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1293,11 +1339,11 @@ INSERT INTO conditions ("time", temperature) VALUES (10, 2); \endif -- No changes SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1319,12 +1365,12 @@ ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only= ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime changes, just new region SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | (4 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1352,13 +1398,14 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- All changes are materialized SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 7 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 -(4 rows) + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -1413,21 +1460,21 @@ SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; \set ON_ERROR_STOP 0 -- should error because it depends of other CAGGs DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:150: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:151: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:152: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:153: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date \set ON_ERROR_STOP 1 -- DROP the 3TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:157: NOTICE: drop cascades to table _timescaledb_internal._hyper_16_14_chunk +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_16_14_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:160: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs @@ -1435,13 +1482,14 @@ TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 7 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 -(4 rows) + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -1450,30 +1498,31 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -- DROP the 2TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:171: NOTICE: drop cascades to table _timescaledb_internal._hyper_15_13_chunk +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_15_13_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:174: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 7 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 -(4 rows) + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) -- DROP the first CAGG should work DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:181: NOTICE: drop cascades to table _timescaledb_internal._hyper_14_12_chunk +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_14_12_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:184: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 \set ON_ERROR_STOP 1 -- Default tests \set IS_DEFAULT_COLUMN_ORDER TRUE @@ -1491,16 +1540,23 @@ Running local hypertable tests SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -1510,7 +1566,7 @@ DROP TABLE IF EXISTS conditions CASCADE; \else \if :IS_TIME_DIMENSION SELECT table_name FROM create_hypertable('conditions', 'time'); -psql:include/cagg_on_cagg_setup.sql:35: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices +psql:include/cagg_on_cagg_setup.sql:43: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices table_name ------------ conditions @@ -1521,9 +1577,9 @@ psql:include/cagg_on_cagg_setup.sql:35: WARNING: column type "timestamp without \endif \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -1538,9 +1594,9 @@ psql:include/cagg_on_cagg_setup.sql:35: WARNING: column type "timestamp without CALL distributed_exec (:'STMT'); \endif SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif \ir include/cagg_on_cagg_common.sql -- This file and its contents are licensed under the Timescale License. @@ -1551,9 +1607,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL @@ -1561,18 +1618,32 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval @@ -1607,8 +1678,8 @@ WITH NO DATA; \endif -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- + bucket | temperature | device_id +--------+-------------+----------- (0 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1616,22 +1687,18 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; --------+------------- (0 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1641,12 +1708,7 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; Sun Jan 02 00:00:00 2022 | 20 (2 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 -(1 row) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); @@ -1657,11 +1719,11 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- Materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1690,11 +1752,11 @@ INSERT INTO conditions ("time", temperature) VALUES (10, 2); \endif -- No changes SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1716,12 +1778,12 @@ ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only= ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime changes, just new region SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 5 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | (4 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -1749,13 +1811,14 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- All changes are materialized SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 7 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 -(4 rows) + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -1810,21 +1873,21 @@ SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; \set ON_ERROR_STOP 0 -- should error because it depends of other CAGGs DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:150: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:151: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:152: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:153: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date \set ON_ERROR_STOP 1 -- DROP the 3TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:157: NOTICE: drop cascades to table _timescaledb_internal._hyper_20_18_chunk +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_20_18_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:160: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs @@ -1832,13 +1895,14 @@ TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 7 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 -(4 rows) + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -1847,30 +1911,31 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -- DROP the 2TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:171: NOTICE: drop cascades to table _timescaledb_internal._hyper_19_17_chunk +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_19_17_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:174: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 10 - Sat Jan 01 01:00:00 2022 | 7 - Sun Jan 02 01:00:00 2022 | 20 - Mon Jan 03 01:00:00 2022 | 2 -(4 rows) + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) -- DROP the first CAGG should work DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:181: NOTICE: drop cascades to table _timescaledb_internal._hyper_18_16_chunk +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_18_16_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:184: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 \set ON_ERROR_STOP 1 -- -- Validation test for variable bucket on top of fixed bucket @@ -2219,16 +2284,23 @@ Running local hypertable tests SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -2248,9 +2320,9 @@ DROP TABLE IF EXISTS conditions CASCADE; \endif \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -2265,9 +2337,9 @@ DROP TABLE IF EXISTS conditions CASCADE; CALL distributed_exec (:'STMT'); \endif SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif \ir include/cagg_on_cagg_common.sql -- This file and its contents are licensed under the Timescale License. @@ -2278,9 +2350,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL @@ -2288,18 +2361,32 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval @@ -2334,8 +2421,8 @@ WITH NO DATA; \endif -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- + bucket | temperature | device_id +--------+-------------+----------- (0 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2343,22 +2430,18 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; --------+------------- (0 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2368,12 +2451,7 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; Sun Jan 02 00:00:00 2022 UTC | 20 (2 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 -(1 row) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); @@ -2384,11 +2462,11 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- Materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2417,11 +2495,11 @@ INSERT INTO conditions ("time", temperature) VALUES (10, 2); \endif -- No changes SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2443,12 +2521,12 @@ ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only= ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime changes, just new region SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | (4 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2476,13 +2554,14 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- All changes are materialized SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 7 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 -(4 rows) + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -2537,21 +2616,21 @@ SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; \set ON_ERROR_STOP 0 -- should error because it depends of other CAGGs DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:150: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:151: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:152: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:153: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date \set ON_ERROR_STOP 1 -- DROP the 3TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:157: NOTICE: drop cascades to table _timescaledb_internal._hyper_29_22_chunk +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_29_22_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:160: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs @@ -2559,13 +2638,14 @@ TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 7 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 -(4 rows) + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -2574,30 +2654,31 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -- DROP the 2TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:171: NOTICE: drop cascades to table _timescaledb_internal._hyper_28_21_chunk +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_28_21_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:174: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 7 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 -(4 rows) + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) -- DROP the first CAGG should work DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:181: NOTICE: drop cascades to table _timescaledb_internal._hyper_27_20_chunk +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_27_20_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:184: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 \set ON_ERROR_STOP 1 -- Default tests \set IS_DEFAULT_COLUMN_ORDER TRUE @@ -2615,16 +2696,23 @@ Running local hypertable tests SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -2644,9 +2732,9 @@ DROP TABLE IF EXISTS conditions CASCADE; \endif \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -2661,9 +2749,9 @@ DROP TABLE IF EXISTS conditions CASCADE; CALL distributed_exec (:'STMT'); \endif SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif \ir include/cagg_on_cagg_common.sql -- This file and its contents are licensed under the Timescale License. @@ -2674,9 +2762,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL @@ -2684,18 +2773,32 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval @@ -2730,8 +2833,8 @@ WITH NO DATA; \endif -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- + bucket | temperature | device_id +--------+-------------+----------- (0 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2739,22 +2842,18 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; --------+------------- (0 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2764,12 +2863,7 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; Sun Jan 02 00:00:00 2022 UTC | 20 (2 rows) -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 -(1 row) - +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); @@ -2780,11 +2874,11 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- Materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2813,11 +2907,11 @@ INSERT INTO conditions ("time", temperature) VALUES (10, 2); \endif -- No changes SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 (3 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2839,12 +2933,12 @@ ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only= ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime changes, just new region SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 5 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | (4 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; @@ -2872,13 +2966,14 @@ CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); -- All changes are materialized SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 7 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 -(4 rows) + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -2933,21 +3028,21 @@ SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; \set ON_ERROR_STOP 0 -- should error because it depends of other CAGGs DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:150: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:151: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:152: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:153: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date \set ON_ERROR_STOP 1 -- DROP the 3TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:157: NOTICE: drop cascades to table _timescaledb_internal._hyper_33_26_chunk +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_33_26_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:160: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs @@ -2955,13 +3050,14 @@ TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 7 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 -(4 rows) + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; bucket | temperature @@ -2970,30 +3066,31 @@ SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -- DROP the 2TH level CAGG don't affect others DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:171: NOTICE: drop cascades to table _timescaledb_internal._hyper_32_25_chunk +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_32_25_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:174: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 \set ON_ERROR_STOP 1 -- should work because dropping the top level CAGG -- don't affect the down level CAGGs SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 10 - Sat Jan 01 01:00:00 2022 UTC | 7 - Sun Jan 02 01:00:00 2022 UTC | 20 - Mon Jan 03 01:00:00 2022 UTC | 2 -(4 rows) + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) -- DROP the first CAGG should work DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:181: NOTICE: drop cascades to table _timescaledb_internal._hyper_31_24_chunk +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_31_24_chunk \set ON_ERROR_STOP 0 -- should error because it was dropped SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:184: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 \set ON_ERROR_STOP 1 -- -- Validation test for variable bucket on top of fixed bucket diff --git a/tsl/test/expected/cagg_on_cagg_joins.out b/tsl/test/expected/cagg_on_cagg_joins.out new file mode 100644 index 00000000000..978b95cf492 --- /dev/null +++ b/tsl/test/expected/cagg_on_cagg_joins.out @@ -0,0 +1,4423 @@ +-- 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. +-- Global test variables +\set IS_DISTRIBUTED FALSE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE +\set IS_JOIN TRUE +-- ######################################################## +-- ## INTEGER data type tests +-- ######################################################## +-- Current test variables +\set IS_TIME_DIMENSION FALSE +\set TIME_DIMENSION_DATATYPE INTEGER +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_5 +\set CAGG_NAME_3TH_LEVEL conditions_summary_3_10 +-- +-- Run common tests for INTEGER +-- +\set BUCKET_WIDTH_1ST 'INTEGER \'1\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' +\set BUCKET_WIDTH_3TH 'INTEGER \'10\'' +-- Different order of time dimension in raw ht +\set IS_DEFAULT_COLUMN_ORDER FALSE +\ir include/cagg_on_cagg_setup.sql +-- 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. +-- CAGGs on CAGGs tests +\if :IS_DISTRIBUTED +\echo 'Running distributed hypertable tests' +\else +\echo 'Running local hypertable tests' +Running local hypertable tests +\endif +SET ROLE :ROLE_DEFAULT_PERM_USER; +DROP TABLE IF EXISTS conditions CASCADE; +psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exist, skipping +\if :IS_DEFAULT_COLUMN_ORDER + CREATE TABLE conditions ( + time :TIME_DIMENSION_DATATYPE NOT NULL, + temperature NUMERIC, + device_id INT + ); +\else + CREATE TABLE conditions ( + temperature NUMERIC, + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT + ); +\endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; +psql:include/cagg_on_cagg_setup.sql:30: NOTICE: table "devices" does not exist, skipping + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif +\if :IS_DISTRIBUTED + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); + \else + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); + \endif +\else + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_hypertable('conditions', 'time'); + \else + SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); + table_name +------------ + conditions +(1 row) + + \endif +\endif +\if :IS_TIME_DIMENSION + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); +\else + CREATE OR REPLACE FUNCTION integer_now() + RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS + $$ + SELECT coalesce(max(time), 0) + FROM conditions + $$; + \if :IS_DISTRIBUTED + SELECT + 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" + \gset + CALL distributed_exec (:'STMT'); + \endif + SELECT set_integer_now_func('conditions', 'integer_now'); + set_integer_now_func +---------------------- + +(1 row) + + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); +\endif +\ir include/cagg_on_cagg_common.sql +-- 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. +-- CAGG on hypertable (1st level) +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + SUM(temperature) AS temperature, + device_id +FROM conditions +GROUP BY 1,3 +WITH NO DATA; +-- CAGG on CAGG (2th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + SUM(temperature) AS temperature +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif +WITH NO DATA; +-- CAGG on CAGG (3th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; +-- Check chunk_interval +\if :IS_TIME_DIMENSION + SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; +\else + SELECT h.table_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; + name | chunk_interval +-------------------------+---------------- + conditions | 10 + conditions_summary_1_1 | 100 + conditions_summary_2_5 | 100 + conditions_summary_3_10 | 100 +(4 rows) + +\endif +-- No data because the CAGGs are just for materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +\if :IS_TIME_DIMENSION +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); +\else +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES (2, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES (10, 2); +\endif +-- No changes +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime changes, just new region +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(4 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 10 | 1 + 0 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 10 | 1 + 0 | 5 | 2 + 0 | 20 | 3 +(3 rows) + +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- All changes are materialized +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +-- TRUNCATE tests +TRUNCATE :CAGG_NAME_2TH_LEVEL; +-- This full refresh will remove all the data from the 3TH level cagg +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Should return no rows +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- If we have all the data in the bottom levels caggs we can rebuild +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Now we have all the data +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +-- DROP tests +\set ON_ERROR_STOP 0 +-- should error because it depends of other CAGGs +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date +\set ON_ERROR_STOP 1 +-- DROP the 3TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_4_4_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- DROP the 2TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_3_3_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) + +-- DROP the first CAGG should work +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_2_2_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- Default tests +\set ON_ERROR_STOP 0 +\set IS_DEFAULT_COLUMN_ORDER TRUE +\ir include/cagg_on_cagg_setup.sql +-- 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. +-- CAGGs on CAGGs tests +\if :IS_DISTRIBUTED +\echo 'Running distributed hypertable tests' +\else +\echo 'Running local hypertable tests' +Running local hypertable tests +\endif +SET ROLE :ROLE_DEFAULT_PERM_USER; +DROP TABLE IF EXISTS conditions CASCADE; +\if :IS_DEFAULT_COLUMN_ORDER + CREATE TABLE conditions ( + time :TIME_DIMENSION_DATATYPE NOT NULL, + temperature NUMERIC, + device_id INT + ); +\else + CREATE TABLE conditions ( + temperature NUMERIC, + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT + ); +\endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif +\if :IS_DISTRIBUTED + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); + \else + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); + \endif +\else + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_hypertable('conditions', 'time'); + \else + SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); + table_name +------------ + conditions +(1 row) + + \endif +\endif +\if :IS_TIME_DIMENSION + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); +\else + CREATE OR REPLACE FUNCTION integer_now() + RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS + $$ + SELECT coalesce(max(time), 0) + FROM conditions + $$; + \if :IS_DISTRIBUTED + SELECT + 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" + \gset + CALL distributed_exec (:'STMT'); + \endif + SELECT set_integer_now_func('conditions', 'integer_now'); + set_integer_now_func +---------------------- + +(1 row) + + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); +\endif +\ir include/cagg_on_cagg_common.sql +-- 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. +-- CAGG on hypertable (1st level) +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + SUM(temperature) AS temperature, + device_id +FROM conditions +GROUP BY 1,3 +WITH NO DATA; +-- CAGG on CAGG (2th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + SUM(temperature) AS temperature +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif +WITH NO DATA; +-- CAGG on CAGG (3th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; +-- Check chunk_interval +\if :IS_TIME_DIMENSION + SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; +\else + SELECT h.table_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; + name | chunk_interval +-------------------------+---------------- + conditions | 10 + conditions_summary_1_1 | 100 + conditions_summary_2_5 | 100 + conditions_summary_3_10 | 100 +(4 rows) + +\endif +-- No data because the CAGGs are just for materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +\if :IS_TIME_DIMENSION +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); +\else +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES (2, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES (10, 2); +\endif +-- No changes +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime changes, just new region +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(4 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 10 | 1 + 0 | 5 | 2 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 10 | 1 + 0 | 5 | 2 + 0 | 20 | 3 +(3 rows) + +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- All changes are materialized +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +-- TRUNCATE tests +TRUNCATE :CAGG_NAME_2TH_LEVEL; +-- This full refresh will remove all the data from the 3TH level cagg +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Should return no rows +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- If we have all the data in the bottom levels caggs we can rebuild +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Now we have all the data +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 5 | 2 + 0 | 10 | 1 + 5 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 0 | 20 | 3 + 0 | 5 | 2 + 0 | 10 | 1 +(3 rows) + +-- DROP tests +\set ON_ERROR_STOP 0 +-- should error because it depends of other CAGGs +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date +\set ON_ERROR_STOP 1 +-- DROP the 3TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_8_9_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- DROP the 2TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_7_8_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- + 1 | 10 | 1 + 2 | 2 | + 2 | 5 | 2 + 5 | 20 | 3 + 10 | 2 | +(5 rows) + +-- DROP the first CAGG should work +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_6_7_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- +-- Validation test for non-multiple bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+---------+-----------+----------+---------+---------+------------- + bucket | integer | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_9.bucket, + _materialized_hypertable_9.temperature + FROM _timescaledb_internal._materialized_hypertable_9 + WHERE _materialized_hypertable_9.bucket < COALESCE(_timescaledb_internal.cagg_watermark(9)::integer, '-2147483648'::integer) +UNION ALL + SELECT time_bucket(2, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.cagg_watermark(9)::integer, '-2147483648'::integer) + GROUP BY (time_bucket(2, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because non-multiple bucket sizes +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [5] should be multiple of the time bucket width of "public.conditions_summary_1" [2]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for equal bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'2\'' +\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+---------+-----------+----------+---------+---------+------------- + bucket | integer | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_10.bucket, + _materialized_hypertable_10.temperature + FROM _timescaledb_internal._materialized_hypertable_10 + WHERE _materialized_hypertable_10.bucket < COALESCE(_timescaledb_internal.cagg_watermark(10)::integer, '-2147483648'::integer) +UNION ALL + SELECT time_bucket(2, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.cagg_watermark(10)::integer, '-2147483648'::integer) + GROUP BY (time_bucket(2, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +SHOULD WORK because new bucket should be greater than previous +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+---------+-----------+----------+---------+---------+------------- + bucket | integer | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_11.bucket, + _materialized_hypertable_11.temperature + FROM _timescaledb_internal._materialized_hypertable_11 + WHERE _materialized_hypertable_11.bucket < COALESCE(_timescaledb_internal.cagg_watermark(11)::integer, '-2147483648'::integer) +UNION ALL + SELECT time_bucket(2, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.cagg_watermark(11)::integer, '-2147483648'::integer) + GROUP BY (time_bucket(2, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for bucket size less than source +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTEGER \'4\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'2\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+---------+-----------+----------+---------+---------+------------- + bucket | integer | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_12.bucket, + _materialized_hypertable_12.temperature + FROM _timescaledb_internal._materialized_hypertable_12 + WHERE _materialized_hypertable_12.bucket < COALESCE(_timescaledb_internal.cagg_watermark(12)::integer, '-2147483648'::integer) +UNION ALL + SELECT time_bucket(4, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.cagg_watermark(12)::integer, '-2147483648'::integer) + GROUP BY (time_bucket(4, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because new bucket should be greater than previous +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [2] should be greater or equal than the time bucket width of "public.conditions_summary_1" [4]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- ######################################################## +-- ## TIMESTAMP data type tests +-- ######################################################## +-- Current test variables +\set IS_TIME_DIMENSION TRUE +\set TIME_DIMENSION_DATATYPE TIMESTAMP +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_hourly +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_daily +\set CAGG_NAME_3TH_LEVEL conditions_summary_3_weekly +\set IS_JOIN TRUE +SET timezone TO 'UTC'; +-- +-- Run common tests for TIMESTAMP +-- +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' +-- Different order of time dimension in raw ht +\set IS_DEFAULT_COLUMN_ORDER FALSE +\ir include/cagg_on_cagg_setup.sql +-- 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. +-- CAGGs on CAGGs tests +\if :IS_DISTRIBUTED +\echo 'Running distributed hypertable tests' +\else +\echo 'Running local hypertable tests' +Running local hypertable tests +\endif +SET ROLE :ROLE_DEFAULT_PERM_USER; +DROP TABLE IF EXISTS conditions CASCADE; +\if :IS_DEFAULT_COLUMN_ORDER + CREATE TABLE conditions ( + time :TIME_DIMENSION_DATATYPE NOT NULL, + temperature NUMERIC, + device_id INT + ); +\else + CREATE TABLE conditions ( + temperature NUMERIC, + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT + ); +\endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif +\if :IS_DISTRIBUTED + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); + \else + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); + \endif +\else + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_hypertable('conditions', 'time'); +psql:include/cagg_on_cagg_setup.sql:43: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices + table_name +------------ + conditions +(1 row) + + \else + SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); + \endif +\endif +\if :IS_TIME_DIMENSION + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); +\else + CREATE OR REPLACE FUNCTION integer_now() + RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS + $$ + SELECT coalesce(max(time), 0) + FROM conditions + $$; + \if :IS_DISTRIBUTED + SELECT + 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" + \gset + CALL distributed_exec (:'STMT'); + \endif + SELECT set_integer_now_func('conditions', 'integer_now'); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); +\endif +\ir include/cagg_on_cagg_common.sql +-- 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. +-- CAGG on hypertable (1st level) +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + SUM(temperature) AS temperature, + device_id +FROM conditions +GROUP BY 1,3 +WITH NO DATA; +-- CAGG on CAGG (2th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + SUM(temperature) AS temperature +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif +WITH NO DATA; +-- CAGG on CAGG (3th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; +-- Check chunk_interval +\if :IS_TIME_DIMENSION + SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; + name | chunk_interval +-----------------------------+---------------- + conditions | @ 7 days + conditions_summary_1_hourly | @ 70 days + conditions_summary_2_daily | @ 70 days + conditions_summary_3_weekly | @ 70 days +(4 rows) + +\else + SELECT h.table_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; +\endif +-- No data because the CAGGs are just for materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +\if :IS_TIME_DIMENSION +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); +\else +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES (2, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES (10, 2); +\endif +-- No changes +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime changes, just new region +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(4 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 10 | 1 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 20 | 3 +(3 rows) + +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- All changes are materialized +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +-- TRUNCATE tests +TRUNCATE :CAGG_NAME_2TH_LEVEL; +-- This full refresh will remove all the data from the 3TH level cagg +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Should return no rows +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- If we have all the data in the bottom levels caggs we can rebuild +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Now we have all the data +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +-- DROP tests +\set ON_ERROR_STOP 0 +-- should error because it depends of other CAGGs +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +\set ON_ERROR_STOP 1 +-- DROP the 3TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_16_14_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- DROP the 2TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_15_13_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) + +-- DROP the first CAGG should work +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_14_12_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- Default tests +\set IS_DEFAULT_COLUMN_ORDER TRUE +\ir include/cagg_on_cagg_setup.sql +-- 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. +-- CAGGs on CAGGs tests +\if :IS_DISTRIBUTED +\echo 'Running distributed hypertable tests' +\else +\echo 'Running local hypertable tests' +Running local hypertable tests +\endif +SET ROLE :ROLE_DEFAULT_PERM_USER; +DROP TABLE IF EXISTS conditions CASCADE; +\if :IS_DEFAULT_COLUMN_ORDER + CREATE TABLE conditions ( + time :TIME_DIMENSION_DATATYPE NOT NULL, + temperature NUMERIC, + device_id INT + ); +\else + CREATE TABLE conditions ( + temperature NUMERIC, + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT + ); +\endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif +\if :IS_DISTRIBUTED + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); + \else + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); + \endif +\else + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_hypertable('conditions', 'time'); +psql:include/cagg_on_cagg_setup.sql:43: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices + table_name +------------ + conditions +(1 row) + + \else + SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); + \endif +\endif +\if :IS_TIME_DIMENSION + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); +\else + CREATE OR REPLACE FUNCTION integer_now() + RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS + $$ + SELECT coalesce(max(time), 0) + FROM conditions + $$; + \if :IS_DISTRIBUTED + SELECT + 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" + \gset + CALL distributed_exec (:'STMT'); + \endif + SELECT set_integer_now_func('conditions', 'integer_now'); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); +\endif +\ir include/cagg_on_cagg_common.sql +-- 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. +-- CAGG on hypertable (1st level) +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + SUM(temperature) AS temperature, + device_id +FROM conditions +GROUP BY 1,3 +WITH NO DATA; +-- CAGG on CAGG (2th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + SUM(temperature) AS temperature +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif +WITH NO DATA; +-- CAGG on CAGG (3th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; +-- Check chunk_interval +\if :IS_TIME_DIMENSION + SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; + name | chunk_interval +-----------------------------+---------------- + conditions | @ 7 days + conditions_summary_1_hourly | @ 70 days + conditions_summary_2_daily | @ 70 days + conditions_summary_3_weekly | @ 70 days +(4 rows) + +\else + SELECT h.table_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; +\endif +-- No data because the CAGGs are just for materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +\if :IS_TIME_DIMENSION +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); +\else +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES (2, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES (10, 2); +\endif +-- No changes +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime changes, just new region +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(4 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 10 | 1 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 20 | 3 +(3 rows) + +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- All changes are materialized +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +-- TRUNCATE tests +TRUNCATE :CAGG_NAME_2TH_LEVEL; +-- This full refresh will remove all the data from the 3TH level cagg +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Should return no rows +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- If we have all the data in the bottom levels caggs we can rebuild +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Now we have all the data +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 5 | 2 + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sun Jan 02 00:00:00 2022 | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 | 20 | 3 + Mon Dec 27 00:00:00 2021 | 5 | 2 + Mon Dec 27 00:00:00 2021 | 10 | 1 +(3 rows) + +-- DROP tests +\set ON_ERROR_STOP 0 +-- should error because it depends of other CAGGs +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +\set ON_ERROR_STOP 1 +-- DROP the 3TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_20_18_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- DROP the 2TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_19_17_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 | 10 | 1 + Sat Jan 01 01:00:00 2022 | 2 | + Sat Jan 01 01:00:00 2022 | 5 | 2 + Sun Jan 02 01:00:00 2022 | 20 | 3 + Mon Jan 03 01:00:00 2022 | 2 | +(5 rows) + +-- DROP the first CAGG should work +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_18_16_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- +-- Validation test for variable bucket on top of fixed bucket +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+-----------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp without time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_21.bucket, + _materialized_hypertable_21.temperature + FROM _timescaledb_internal._materialized_hypertable_21 + WHERE _materialized_hypertable_21.bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(21)), '-infinity'::timestamp without time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(21)), '-infinity'::timestamp without time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with fixed-width bucket on top of one using variable-width bucket +DETAIL: Continuous aggregate with a fixed time bucket width (e.g. 61 days) cannot be created on top of one using variable time bucket width (e.g. 1 month). +The variance can lead to the fixed width one not being a multiple of the variable width one. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for non-multiple bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+-----------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp without time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_22.bucket, + _materialized_hypertable_22.temperature + FROM _timescaledb_internal._materialized_hypertable_22 + WHERE _materialized_hypertable_22.bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(22)), '-infinity'::timestamp without time zone) +UNION ALL + SELECT time_bucket('@ 2 hours'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(22)), '-infinity'::timestamp without time zone) + GROUP BY (time_bucket('@ 2 hours'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because non-multiple bucket sizes +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 3 hours] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 2 hours]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for equal bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+-----------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp without time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_23.bucket, + _materialized_hypertable_23.temperature + FROM _timescaledb_internal._materialized_hypertable_23 + WHERE _materialized_hypertable_23.bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(23)), '-infinity'::timestamp without time zone) +UNION ALL + SELECT time_bucket('@ 1 hour'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(23)), '-infinity'::timestamp without time zone) + GROUP BY (time_bucket('@ 1 hour'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +SHOULD WORK because new bucket should be greater than previous +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+-----------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp without time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_24.bucket, + _materialized_hypertable_24.temperature + FROM _timescaledb_internal._materialized_hypertable_24 + WHERE _materialized_hypertable_24.bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(24)), '-infinity'::timestamp without time zone) +UNION ALL + SELECT time_bucket('@ 1 hour'::interval, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(24)), '-infinity'::timestamp without time zone) + GROUP BY (time_bucket('@ 1 hour'::interval, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for bucket size less than source +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+-----------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp without time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_25.bucket, + _materialized_hypertable_25.temperature + FROM _timescaledb_internal._materialized_hypertable_25 + WHERE _materialized_hypertable_25.bucket < COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(25)), '-infinity'::timestamp without time zone) +UNION ALL + SELECT time_bucket('@ 2 hours'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp_without_timezone(_timescaledb_internal.cagg_watermark(25)), '-infinity'::timestamp without time zone) + GROUP BY (time_bucket('@ 2 hours'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because new bucket should be greater than previous +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 1 hour] should be greater or equal than the time bucket width of "public.conditions_summary_1" [@ 2 hours]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- ######################################################## +-- ## TIMESTAMPTZ data type tests +-- ######################################################## +-- Current test variables +\set IS_TIME_DIMENSION TRUE +\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_hourly +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_daily +\set CAGG_NAME_3TH_LEVEL conditions_summary_3_weekly +SET timezone TO 'UTC'; +-- +-- Run common tests for TIMESTAMPTZ +-- +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' +-- Different order of time dimension in raw ht +\set ON_ERROR_STOP 0 +\set IS_DEFAULT_COLUMN_ORDER FALSE +\ir include/cagg_on_cagg_setup.sql +-- 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. +-- CAGGs on CAGGs tests +\if :IS_DISTRIBUTED +\echo 'Running distributed hypertable tests' +\else +\echo 'Running local hypertable tests' +Running local hypertable tests +\endif +SET ROLE :ROLE_DEFAULT_PERM_USER; +DROP TABLE IF EXISTS conditions CASCADE; +\if :IS_DEFAULT_COLUMN_ORDER + CREATE TABLE conditions ( + time :TIME_DIMENSION_DATATYPE NOT NULL, + temperature NUMERIC, + device_id INT + ); +\else + CREATE TABLE conditions ( + temperature NUMERIC, + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT + ); +\endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif +\if :IS_DISTRIBUTED + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); + \else + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); + \endif +\else + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_hypertable('conditions', 'time'); + table_name +------------ + conditions +(1 row) + + \else + SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); + \endif +\endif +\if :IS_TIME_DIMENSION + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); +\else + CREATE OR REPLACE FUNCTION integer_now() + RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS + $$ + SELECT coalesce(max(time), 0) + FROM conditions + $$; + \if :IS_DISTRIBUTED + SELECT + 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" + \gset + CALL distributed_exec (:'STMT'); + \endif + SELECT set_integer_now_func('conditions', 'integer_now'); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); +\endif +\ir include/cagg_on_cagg_common.sql +-- 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. +-- CAGG on hypertable (1st level) +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + SUM(temperature) AS temperature, + device_id +FROM conditions +GROUP BY 1,3 +WITH NO DATA; +-- CAGG on CAGG (2th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + SUM(temperature) AS temperature +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif +WITH NO DATA; +-- CAGG on CAGG (3th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; +-- Check chunk_interval +\if :IS_TIME_DIMENSION + SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; + name | chunk_interval +-----------------------------+---------------- + conditions | @ 7 days + conditions_summary_1_hourly | @ 70 days + conditions_summary_2_daily | @ 70 days + conditions_summary_3_weekly | @ 70 days +(4 rows) + +\else + SELECT h.table_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; +\endif +-- No data because the CAGGs are just for materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +\if :IS_TIME_DIMENSION +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); +\else +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES (2, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES (10, 2); +\endif +-- No changes +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime changes, just new region +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(4 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 +(3 rows) + +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- All changes are materialized +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +-- TRUNCATE tests +TRUNCATE :CAGG_NAME_2TH_LEVEL; +-- This full refresh will remove all the data from the 3TH level cagg +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Should return no rows +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- If we have all the data in the bottom levels caggs we can rebuild +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Now we have all the data +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +-- DROP tests +\set ON_ERROR_STOP 0 +-- should error because it depends of other CAGGs +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +\set ON_ERROR_STOP 1 +-- DROP the 3TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_29_22_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- DROP the 2TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_28_21_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) + +-- DROP the first CAGG should work +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_27_20_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- Default tests +\set ON_ERROR_STOP 0 +\set IS_DEFAULT_COLUMN_ORDER TRUE +\ir include/cagg_on_cagg_setup.sql +-- 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. +-- CAGGs on CAGGs tests +\if :IS_DISTRIBUTED +\echo 'Running distributed hypertable tests' +\else +\echo 'Running local hypertable tests' +Running local hypertable tests +\endif +SET ROLE :ROLE_DEFAULT_PERM_USER; +DROP TABLE IF EXISTS conditions CASCADE; +\if :IS_DEFAULT_COLUMN_ORDER + CREATE TABLE conditions ( + time :TIME_DIMENSION_DATATYPE NOT NULL, + temperature NUMERIC, + device_id INT + ); +\else + CREATE TABLE conditions ( + temperature NUMERIC, + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT + ); +\endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif +\if :IS_DISTRIBUTED + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); + \else + SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); + \endif +\else + \if :IS_TIME_DIMENSION + SELECT table_name FROM create_hypertable('conditions', 'time'); + table_name +------------ + conditions +(1 row) + + \else + SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); + \endif +\endif +\if :IS_TIME_DIMENSION + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); +\else + CREATE OR REPLACE FUNCTION integer_now() + RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS + $$ + SELECT coalesce(max(time), 0) + FROM conditions + $$; + \if :IS_DISTRIBUTED + SELECT + 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" + \gset + CALL distributed_exec (:'STMT'); + \endif + SELECT set_integer_now_func('conditions', 'integer_now'); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); +\endif +\ir include/cagg_on_cagg_common.sql +-- 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. +-- CAGG on hypertable (1st level) +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + SUM(temperature) AS temperature, + device_id +FROM conditions +GROUP BY 1,3 +WITH NO DATA; +-- CAGG on CAGG (2th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS +SELECT + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + SUM(temperature) AS temperature +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif +WITH NO DATA; +-- CAGG on CAGG (3th level) +CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; +-- Check chunk_interval +\if :IS_TIME_DIMENSION + SELECT h.table_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, _timescaledb_internal.to_interval(d.interval_length) AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; + name | chunk_interval +-----------------------------+---------------- + conditions | @ 7 days + conditions_summary_1_hourly | @ 70 days + conditions_summary_2_daily | @ 70 days + conditions_summary_3_weekly | @ 70 days +(4 rows) + +\else + SELECT h.table_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.hypertable h + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id + WHERE h.table_name = 'conditions' + UNION ALL + SELECT c.user_view_name AS name, d.interval_length AS chunk_interval + FROM _timescaledb_catalog.continuous_agg c + LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id + WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') + ORDER BY 1, 2; +\endif +-- No data because the CAGGs are just for materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Materialized data +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +\if :IS_TIME_DIMENSION +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); +\else +-- Invalidate an old region +INSERT INTO conditions ("time", temperature) VALUES (2, 2); +-- New region +INSERT INTO conditions ("time", temperature) VALUES (10, 2); +\endif +-- No changes +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +-- Turn CAGGs into Realtime +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +-- Realtime changes, just new region +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(4 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 +(3 rows) + +-- Turn CAGGs into materialized only again +ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); +ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); +-- Refresh all data +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- All changes are materialized +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +-- TRUNCATE tests +TRUNCATE :CAGG_NAME_2TH_LEVEL; +-- This full refresh will remove all the data from the 3TH level cagg +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Should return no rows +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- If we have all the data in the bottom levels caggs we can rebuild +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); +-- Now we have all the data +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 5 | 2 + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sun Jan 02 00:00:00 2022 UTC | 20 | 3 +(3 rows) + +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Mon Dec 27 00:00:00 2021 UTC | 20 | 3 + Mon Dec 27 00:00:00 2021 UTC | 5 | 2 + Mon Dec 27 00:00:00 2021 UTC | 10 | 1 +(3 rows) + +-- DROP tests +\set ON_ERROR_STOP 0 +-- should error because it depends of other CAGGs +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date +\set ON_ERROR_STOP 1 +-- DROP the 3TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_33_26_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; +CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); +CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) + +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; + bucket | temperature | device_id +--------+-------------+----------- +(0 rows) + +-- DROP the 2TH level CAGG don't affect others +DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_32_25_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- should work because dropping the top level CAGG +-- don't affect the down level CAGGs +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; + bucket | temperature | device_id +------------------------------+-------------+----------- + Sat Jan 01 00:00:00 2022 UTC | 10 | 1 + Sat Jan 01 01:00:00 2022 UTC | 2 | + Sat Jan 01 01:00:00 2022 UTC | 5 | 2 + Sun Jan 02 01:00:00 2022 UTC | 20 | 3 + Mon Jan 03 01:00:00 2022 UTC | 2 | +(5 rows) + +-- DROP the first CAGG should work +DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; +psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_31_24_chunk +\set ON_ERROR_STOP 0 +-- should error because it was dropped +SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; +psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 +\set ON_ERROR_STOP 1 +-- +-- Validation test for variable bucket on top of fixed bucket +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_34.bucket, + _materialized_hypertable_34.temperature + FROM _timescaledb_internal._materialized_hypertable_34 + WHERE _materialized_hypertable_34.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(34)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(34)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with fixed-width bucket on top of one using variable-width bucket +DETAIL: Continuous aggregate with a fixed time bucket width (e.g. 61 days) cannot be created on top of one using variable time bucket width (e.g. 1 month). +The variance can lead to the fixed width one not being a multiple of the variable width one. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for non-multiple bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_35.bucket, + _materialized_hypertable_35.temperature + FROM _timescaledb_internal._materialized_hypertable_35 + WHERE _materialized_hypertable_35.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(35)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 2 hours'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(35)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 2 hours'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because non-multiple bucket sizes +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 3 hours] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 2 hours]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for equal bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_36.bucket, + _materialized_hypertable_36.temperature + FROM _timescaledb_internal._materialized_hypertable_36 + WHERE _materialized_hypertable_36.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(36)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 hour'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(36)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 hour'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +SHOULD WORK because new bucket should be greater than previous +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_37.bucket, + _materialized_hypertable_37.temperature + FROM _timescaledb_internal._materialized_hypertable_37 + WHERE _materialized_hypertable_37.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(37)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 hour'::interval, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(37)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 hour'::interval, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validation test for bucket size less than source +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_38.bucket, + _materialized_hypertable_38.temperature + FROM _timescaledb_internal._materialized_hypertable_38 + WHERE _materialized_hypertable_38.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(38)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 2 hours'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(38)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 2 hours'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because new bucket should be greater than previous +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 1 hour] should be greater or equal than the time bucket width of "public.conditions_summary_1" [@ 2 hours]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Validations using time bucket with timezone (ref issue #5126) +-- +\set ON_ERROR_STOP 0 +\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_5m +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_1h +\set BUCKET_TZNAME_1ST 'US/Pacific' +\set BUCKET_TZNAME_2TH 'US/Pacific' +\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_39.bucket, + _materialized_hypertable_39.temperature + FROM _timescaledb_internal._materialized_hypertable_39 + WHERE _materialized_hypertable_39.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(39)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 5 mins'::interval, conditions."time", 'US/Pacific'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(39)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 5 mins'::interval, conditions."time", 'US/Pacific'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_40.bucket, + _materialized_hypertable_40.temperature + FROM _timescaledb_internal._materialized_hypertable_40 + WHERE _materialized_hypertable_40.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(40)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 hour'::interval, conditions_summary_1.bucket, 'US/Pacific'::text) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(40)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 hour'::interval, conditions_summary_1.bucket, 'US/Pacific'::text)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'16 minutes\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_41.bucket, + _materialized_hypertable_41.temperature + FROM _timescaledb_internal._materialized_hypertable_41 + WHERE _materialized_hypertable_41.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(41)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 5 mins'::interval, conditions."time", 'US/Pacific'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(41)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 5 mins'::interval, conditions."time", 'US/Pacific'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD ERROR because non-multiple bucket sizes +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 16 mins] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 5 mins]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Variable bucket size with the same timezones +-- +\set BUCKET_TZNAME_1ST 'UTC' +\set BUCKET_TZNAME_2TH 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_42.bucket, + _materialized_hypertable_42.temperature + FROM _timescaledb_internal._materialized_hypertable_42 + WHERE _materialized_hypertable_42.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(42)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(42)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_43.bucket, + _materialized_hypertable_43.temperature + FROM _timescaledb_internal._materialized_hypertable_43 + WHERE _materialized_hypertable_43.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(43)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket, 'UTC'::text) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(43)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket, 'UTC'::text)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- Variable bucket size with different timezones +-- +\set BUCKET_TZNAME_1ST 'US/Pacific' +\set BUCKET_TZNAME_2TH 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_44.bucket, + _materialized_hypertable_44.temperature + FROM _timescaledb_internal._materialized_hypertable_44 + WHERE _materialized_hypertable_44.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(44)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 day'::interval, conditions."time", 'US/Pacific'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(44)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 day'::interval, conditions."time", 'US/Pacific'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_45.bucket, + _materialized_hypertable_45.temperature + FROM _timescaledb_internal._materialized_hypertable_45 + WHERE _materialized_hypertable_45.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(45)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket, 'UTC'::text) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(45)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket, 'UTC'::text)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- TZ bucket on top of non-TZ bucket +-- +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE +\set BUCKET_TZNAME_2TH 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_46.bucket, + _materialized_hypertable_46.temperature + FROM _timescaledb_internal._materialized_hypertable_46 + WHERE _materialized_hypertable_46.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(46)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 day'::interval, conditions."time") AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(46)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_47.bucket, + _materialized_hypertable_47.temperature + FROM _timescaledb_internal._materialized_hypertable_47 + WHERE _materialized_hypertable_47.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(47)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket, 'UTC'::text) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(47)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket, 'UTC'::text)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- +-- non-TZ bucket on top of TZ bucket +-- +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE +\set BUCKET_TZNAME_1ST 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_48.bucket, + _materialized_hypertable_48.temperature + FROM _timescaledb_internal._materialized_hypertable_48 + WHERE _materialized_hypertable_48.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(48)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(48)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_49.bucket, + _materialized_hypertable_49.temperature + FROM _timescaledb_internal._materialized_hypertable_49 + WHERE _materialized_hypertable_49.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(49)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(49)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +-- test some intuitive intervals that should work but +-- were not working due to unix epochs +-- validation test for 1 year on top of one day +-- validation test for 1 year on top of 1 month +-- validation test for 1 year on top of 1 week +-- bug report 5231 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_50.bucket, + _materialized_hypertable_50.temperature + FROM _timescaledb_internal._materialized_hypertable_50 + WHERE _materialized_hypertable_50.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(50)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(50)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_51.bucket, + _materialized_hypertable_51.temperature + FROM _timescaledb_internal._materialized_hypertable_51 + WHERE _materialized_hypertable_51.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(51)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 year'::interval, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(51)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 year'::interval, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'3 month\'' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_52.bucket, + _materialized_hypertable_52.temperature + FROM _timescaledb_internal._materialized_hypertable_52 + WHERE _materialized_hypertable_52.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(52)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(52)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 day'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_53.bucket, + _materialized_hypertable_53.temperature + FROM _timescaledb_internal._materialized_hypertable_53 + WHERE _materialized_hypertable_53.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(53)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 3 mons'::interval, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(53)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 3 mons'::interval, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_54.bucket, + _materialized_hypertable_54.temperature + FROM _timescaledb_internal._materialized_hypertable_54 + WHERE _materialized_hypertable_54.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(54)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 mon'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(54)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 mon'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_2TH_LEVEL + View "public.conditions_summary_2" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_55.bucket, + _materialized_hypertable_55.temperature + FROM _timescaledb_internal._materialized_hypertable_55 + WHERE _materialized_hypertable_55.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(55)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 1 year'::interval, conditions_summary_1.bucket) AS bucket, + sum(conditions_summary_1.temperature) AS temperature + FROM conditions_summary_1 + WHERE conditions_summary_1.bucket >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(55)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 1 year'::interval, conditions_summary_1.bucket)); + +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_56.bucket, + _materialized_hypertable_56.temperature + FROM _timescaledb_internal._materialized_hypertable_56 + WHERE _materialized_hypertable_56.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(56)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 7 days'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(56)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 7 days'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 360 days] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 7 days]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\ir include/cagg_on_cagg_validations.sql +-- 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. +\set CAGG_NAME_1ST_LEVEL conditions_summary_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2 +-- +-- CAGG on hypertable (1st level) +-- +CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_1ST + time_bucket(:BUCKET_WIDTH_1ST, "time", :'BUCKET_TZNAME_1ST') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, + \endif + SUM(temperature) AS temperature +FROM conditions +GROUP BY 1 +WITH NO DATA; +\d+ :CAGG_NAME_1ST_LEVEL + View "public.conditions_summary_1" + Column | Type | Collation | Nullable | Default | Storage | Description +-------------+--------------------------+-----------+----------+---------+---------+------------- + bucket | timestamp with time zone | | | | plain | + temperature | numeric | | | | main | +View definition: + SELECT _materialized_hypertable_57.bucket, + _materialized_hypertable_57.temperature + FROM _timescaledb_internal._materialized_hypertable_57 + WHERE _materialized_hypertable_57.bucket < COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(57)), '-infinity'::timestamp with time zone) +UNION ALL + SELECT time_bucket('@ 7 days'::interval, conditions."time", 'UTC'::text) AS bucket, + sum(conditions.temperature) AS temperature + FROM conditions + WHERE conditions."time" >= COALESCE(_timescaledb_internal.to_timestamp(_timescaledb_internal.cagg_watermark(57)), '-infinity'::timestamp with time zone) + GROUP BY (time_bucket('@ 7 days'::interval, conditions."time", 'UTC'::text)); + +-- +-- CAGG on CAGG (2th level) +-- +\set VERBOSITY default +\set ON_ERROR_STOP 0 +\echo :WARNING_MESSAGE +-- SHOULD WORK +CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL +WITH (timescaledb.continuous) AS +SELECT + \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH + time_bucket(:BUCKET_WIDTH_2TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket, + \else + time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, + \endif + SUM(temperature) AS temperature +FROM :CAGG_NAME_1ST_LEVEL +GROUP BY 1 +WITH NO DATA; +psql:include/cagg_on_cagg_validations.sql:43: ERROR: cannot create continuous aggregate with incompatible bucket width +DETAIL: Time bucket width of "public.conditions_summary_2" [@ 30 days] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 7 days]. +\d+ :CAGG_NAME_2TH_LEVEL +\set ON_ERROR_STOP 1 +\set VERBOSITY terse +-- +-- Cleanup +-- +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL; +psql:include/cagg_on_cagg_validations.sql:53: NOTICE: materialized view "conditions_summary_2" does not exist, skipping +DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index f123b060abc..9cba463d471 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -63,6 +63,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) cagg_migrate_dist_ht.sql cagg_multi.sql cagg_on_cagg.sql + cagg_on_cagg_joins.sql cagg_on_cagg_dist_ht.sql continuous_aggs_deprecated.sql cagg_tableam.sql diff --git a/tsl/test/sql/cagg_joins.sql.in b/tsl/test/sql/cagg_joins.sql.in index eefd2eb6a9f..0b5dd345676 100644 --- a/tsl/test/sql/cagg_joins.sql.in +++ b/tsl/test/sql/cagg_joins.sql.in @@ -96,10 +96,11 @@ SELECT time_bucket(INTERVAL '1 day', day) AS bucket, AVG(temperature), MAX(temperature), MIN(temperature), - name + name, + devices.device_id AS thermo_id FROM conditions, devices WHERE conditions.device_id = devices.device_id -GROUP BY name, bucket; +GROUP BY name, bucket, thermo_id; CREATE MATERIALIZED VIEW conditions_summary_daily_reorder WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS @@ -211,7 +212,8 @@ CREATE MATERIALIZED VIEW cagg_on_cagg WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(INTERVAL '1 day', bucket) AS bucket, SUM(avg) AS temperature -FROM conditions_summary_daily +FROM conditions_summary_daily, devices +WHERE devices.device_id = conditions_summary_daily.thermo_id GROUP BY 1; \set VERBOSITY terse @@ -319,24 +321,24 @@ FROM conditions, devices WHERE conditions.device_id = devices.device_id GROUP BY name, bucket, devices.device_id; ---Errors out for join between cagg and normal table +--Join between cagg and normal table CREATE MATERIALIZED VIEW conditions_summary_daily_nested WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, devices.name FROM conditions_summary_daily_cagg cagg, devices WHERE cagg.device_id = devices.device_id -GROUP BY devices.name, bucket; +GROUP BY 1,2; --Error out for join between cagg and hypertable -CREATE MATERIALIZED VIEW conditions_summary_daily_nested +CREATE MATERIALIZED VIEW conditions_summary_daily_nested_ht WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) AS SELECT time_bucket(INTERVAL '1 day', cagg.bucket) AS bucket, cagg.name, conditions.temperature FROM conditions_summary_daily_cagg cagg, conditions WHERE cagg.device_id = conditions.device_id -GROUP BY conditions.temperature, bucket, cagg.name; +GROUP BY 1,2,3; \set VERBOSITY terse DROP TABLE conditions CASCADE; diff --git a/tsl/test/sql/cagg_on_cagg.sql b/tsl/test/sql/cagg_on_cagg.sql index a0025cd186c..95460678c1c 100644 --- a/tsl/test/sql/cagg_on_cagg.sql +++ b/tsl/test/sql/cagg_on_cagg.sql @@ -6,7 +6,7 @@ \set IS_DISTRIBUTED FALSE \set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE \set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE - +\set IS_JOIN FALSE -- ######################################################## -- ## INTEGER data type tests -- ######################################################## diff --git a/tsl/test/sql/cagg_on_cagg_joins.sql b/tsl/test/sql/cagg_on_cagg_joins.sql new file mode 100644 index 00000000000..3611c5d3264 --- /dev/null +++ b/tsl/test/sql/cagg_on_cagg_joins.sql @@ -0,0 +1,288 @@ +-- 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. + +-- Global test variables +\set IS_DISTRIBUTED FALSE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE +\set IS_JOIN TRUE +-- ######################################################## +-- ## INTEGER data type tests +-- ######################################################## + +-- Current test variables +\set IS_TIME_DIMENSION FALSE +\set TIME_DIMENSION_DATATYPE INTEGER +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_1 +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_5 +\set CAGG_NAME_3TH_LEVEL conditions_summary_3_10 + +-- +-- Run common tests for INTEGER +-- +\set BUCKET_WIDTH_1ST 'INTEGER \'1\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' +\set BUCKET_WIDTH_3TH 'INTEGER \'10\'' + +-- Different order of time dimension in raw ht +\set IS_DEFAULT_COLUMN_ORDER FALSE +\ir include/cagg_on_cagg_setup.sql +\ir include/cagg_on_cagg_common.sql + +-- Default tests +\set ON_ERROR_STOP 0 +\set IS_DEFAULT_COLUMN_ORDER TRUE +\ir include/cagg_on_cagg_setup.sql +\ir include/cagg_on_cagg_common.sql + +-- +-- Validation test for non-multiple bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for equal bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'2\'' +\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for bucket size less than source +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTEGER \'4\'' +\set BUCKET_WIDTH_2TH 'INTEGER \'2\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql + +-- ######################################################## +-- ## TIMESTAMP data type tests +-- ######################################################## + +-- Current test variables +\set IS_TIME_DIMENSION TRUE +\set TIME_DIMENSION_DATATYPE TIMESTAMP +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_hourly +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_daily +\set CAGG_NAME_3TH_LEVEL conditions_summary_3_weekly +\set IS_JOIN TRUE +SET timezone TO 'UTC'; + +-- +-- Run common tests for TIMESTAMP +-- +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' + +-- Different order of time dimension in raw ht +\set IS_DEFAULT_COLUMN_ORDER FALSE +\ir include/cagg_on_cagg_setup.sql +\ir include/cagg_on_cagg_common.sql + +-- Default tests +\set IS_DEFAULT_COLUMN_ORDER TRUE +\ir include/cagg_on_cagg_setup.sql +\ir include/cagg_on_cagg_common.sql + +-- +-- Validation test for variable bucket on top of fixed bucket +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for non-multiple bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for equal bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for bucket size less than source +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql + +-- ######################################################## +-- ## TIMESTAMPTZ data type tests +-- ######################################################## + +-- Current test variables +\set IS_TIME_DIMENSION TRUE +\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_hourly +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_daily +\set CAGG_NAME_3TH_LEVEL conditions_summary_3_weekly + +SET timezone TO 'UTC'; + +-- +-- Run common tests for TIMESTAMPTZ +-- +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' + +-- Different order of time dimension in raw ht +\set ON_ERROR_STOP 0 +\set IS_DEFAULT_COLUMN_ORDER FALSE +\ir include/cagg_on_cagg_setup.sql +\ir include/cagg_on_cagg_common.sql + +-- Default tests +\set ON_ERROR_STOP 0 +\set IS_DEFAULT_COLUMN_ORDER TRUE +\ir include/cagg_on_cagg_setup.sql +\ir include/cagg_on_cagg_common.sql + +-- +-- Validation test for variable bucket on top of fixed bucket +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for non-multiple bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for equal bucket sizes +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validation test for bucket size less than source +-- +\set ON_ERROR_STOP 0 +\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Validations using time bucket with timezone (ref issue #5126) +-- +\set ON_ERROR_STOP 0 +\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE +\set CAGG_NAME_1ST_LEVEL conditions_summary_1_5m +\set CAGG_NAME_2TH_LEVEL conditions_summary_2_1h +\set BUCKET_TZNAME_1ST 'US/Pacific' +\set BUCKET_TZNAME_2TH 'US/Pacific' +\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql + +\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'16 minutes\'' +\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Variable bucket size with the same timezones +-- +\set BUCKET_TZNAME_1ST 'UTC' +\set BUCKET_TZNAME_2TH 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql + +-- +-- Variable bucket size with different timezones +-- +\set BUCKET_TZNAME_1ST 'US/Pacific' +\set BUCKET_TZNAME_2TH 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql + +-- +-- TZ bucket on top of non-TZ bucket +-- +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE +\set BUCKET_TZNAME_2TH 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql + +-- +-- non-TZ bucket on top of TZ bucket +-- +\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE +\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE +\set BUCKET_TZNAME_1ST 'UTC' +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\set WARNING_MESSAGE '-- SHOULD WORK' +\ir include/cagg_on_cagg_validations.sql + +-- test some intuitive intervals that should work but +-- were not working due to unix epochs +-- validation test for 1 year on top of one day +-- validation test for 1 year on top of 1 month +-- validation test for 1 year on top of 1 week + +-- bug report 5231 +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' +\ir include/cagg_on_cagg_validations.sql + +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'3 month\'' +\ir include/cagg_on_cagg_validations.sql + +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' +\ir include/cagg_on_cagg_validations.sql + +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' +\ir include/cagg_on_cagg_validations.sql + +\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' +\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' +\ir include/cagg_on_cagg_validations.sql diff --git a/tsl/test/sql/include/cagg_on_cagg_common.sql b/tsl/test/sql/include/cagg_on_cagg_common.sql index 22bfbb1ac5c..f6d4c759590 100644 --- a/tsl/test/sql/include/cagg_on_cagg_common.sql +++ b/tsl/test/sql/include/cagg_on_cagg_common.sql @@ -7,9 +7,10 @@ CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature + SUM(temperature) AS temperature, + device_id FROM conditions -GROUP BY 1 +GROUP BY 1,3 WITH NO DATA; -- CAGG on CAGG (2th level) @@ -18,19 +19,34 @@ WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS SELECT time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, SUM(temperature) AS temperature -FROM :CAGG_NAME_1ST_LEVEL -GROUP BY 1 +\if :IS_JOIN + , :CAGG_NAME_1ST_LEVEL.device_id + FROM :CAGG_NAME_1ST_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id + GROUP BY 1,3 +\else + FROM :CAGG_NAME_1ST_LEVEL + GROUP BY 1 +\endif + WITH NO DATA; -- CAGG on CAGG (3th level) CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature -FROM :CAGG_NAME_2TH_LEVEL -GROUP BY 1 -WITH NO DATA; + WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS + SELECT + time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, + SUM(temperature) AS temperature + \if :IS_JOIN + , :CAGG_NAME_2TH_LEVEL.device_id + FROM :CAGG_NAME_2TH_LEVEL, devices + WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id + GROUP BY 1,3 + \else + FROM :CAGG_NAME_2TH_LEVEL + GROUP BY 1 + \endif + WITH NO DATA; -- Check chunk_interval \if :IS_TIME_DIMENSION @@ -61,17 +77,17 @@ WITH NO DATA; -- No data because the CAGGs are just for materialized data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into Realtime ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); +--ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); -- Realtime data SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; +--SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -- Turn CAGGs into materialized only again ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); diff --git a/tsl/test/sql/include/cagg_on_cagg_setup.sql b/tsl/test/sql/include/cagg_on_cagg_setup.sql index 207ed3f346c..d402990d2f6 100644 --- a/tsl/test/sql/include/cagg_on_cagg_setup.sql +++ b/tsl/test/sql/include/cagg_on_cagg_setup.sql @@ -13,17 +13,25 @@ SET ROLE :ROLE_DEFAULT_PERM_USER; DROP TABLE IF EXISTS conditions CASCADE; \if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( + CREATE TABLE conditions ( time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC + temperature NUMERIC, + device_id INT ); \else - CREATE TABLE conditions ( + CREATE TABLE conditions ( temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL + time :TIME_DIMENSION_DATATYPE NOT NULL, + device_id INT ); \endif +\if :IS_JOIN + DROP TABLE IF EXISTS devices CASCADE; + CREATE TABLE devices ( device_id int not null, name text, location text); + INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); +\endif + \if :IS_DISTRIBUTED \if :IS_TIME_DIMENSION SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); @@ -39,9 +47,9 @@ DROP TABLE IF EXISTS conditions CASCADE; \endif \if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 00:00:00-00', 10); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00', 5); - INSERT INTO conditions ("time", temperature) VALUES ('2022-01-02 01:00:00-00', 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); \else CREATE OR REPLACE FUNCTION integer_now() RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS @@ -58,8 +66,7 @@ DROP TABLE IF EXISTS conditions CASCADE; \endif SELECT set_integer_now_func('conditions', 'integer_now'); - - INSERT INTO conditions ("time", temperature) VALUES (1, 10); - INSERT INTO conditions ("time", temperature) VALUES (2, 5); - INSERT INTO conditions ("time", temperature) VALUES (5, 20); + INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); + INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); + INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); \endif