-- 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_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE
\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE
\set IS_JOIN TRUE
\set INTERVAL_TEST FALSE
-- ########################################################
-- ## 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
SET ROLE :ROLE_DEFAULT_PERM_USER;
DROP TABLE IF EXISTS conditions CASCADE;
psql:include/cagg_on_cagg_setup.sql:8: 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:24: 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_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

\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
  $$;
  SELECT set_integer_now_func('conditions', 'integer_now');
 set_integer_now_func 
----------------------
 

    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
ORDER BY 1, 2, 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
  , devices.device_id
  , devices.name
  FROM :CAGG_NAME_1ST_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id
  GROUP BY 1, 3, 4
  ORDER BY 1, 2, 3, 4
\else
  FROM :CAGG_NAME_1ST_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\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
  , :CAGG_NAME_2TH_LEVEL.name
  , devices.location
  FROM :CAGG_NAME_2TH_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id
  GROUP BY 1, 3, 4, 5
  ORDER BY 1, 2, 3, 4, 5
\else
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\endif
WITH NO DATA;
-- Check chunk_interval
\if :IS_TIME_DIMENSION
  SELECT h.table_name AS name, _timescaledb_functions.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_functions.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

\endif
-- No data because the CAGGs are just for materialized data
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
 bucket | temperature | device_id 
--------+-------------+-----------

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

\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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           2 |          
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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:172: 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:173: 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:174: 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:175: 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:179: 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;
psql:include/cagg_on_cagg_common.sql:182: 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           2 |          
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

-- DROP the 2TH level CAGG don't affect others
DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL;
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:196: 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           2 |          
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

-- DROP the first CAGG should work
DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:203: NOTICE:  drop cascades to table _timescaledb_internal._hyper_2_7_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:206: 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
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_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

\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
  $$;
  SELECT set_integer_now_func('conditions', 'integer_now');
 set_integer_now_func 
----------------------
 

    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
ORDER BY 1, 2, 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
  , devices.device_id
  , devices.name
  FROM :CAGG_NAME_1ST_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id
  GROUP BY 1, 3, 4
  ORDER BY 1, 2, 3, 4
\else
  FROM :CAGG_NAME_1ST_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\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
  , :CAGG_NAME_2TH_LEVEL.name
  , devices.location
  FROM :CAGG_NAME_2TH_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id
  GROUP BY 1, 3, 4, 5
  ORDER BY 1, 2, 3, 4, 5
\else
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\endif
WITH NO DATA;
-- Check chunk_interval
\if :IS_TIME_DIMENSION
  SELECT h.table_name AS name, _timescaledb_functions.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_functions.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

\endif
-- No data because the CAGGs are just for materialized data
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
 bucket | temperature | device_id 
--------+-------------+-----------

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

\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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           2 |          
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
 bucket | temperature | device_id |   name   
--------+-------------+-----------+----------
      0 |           5 |         2 | thermo_2
      0 |          10 |         1 | thermo_1
      5 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id |   name   | location 
--------+-------------+-----------+----------+----------
      0 |           5 |         2 | thermo_2 | Berlin
      0 |          10 |         1 | thermo_1 | Moscow
      0 |          20 |         3 | thermo_3 | London

-- 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:172: 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:173: 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:174: 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:175: 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:179: NOTICE:  drop cascades to table _timescaledb_internal._hyper_8_11_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_3TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:182: 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           2 |          
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

-- DROP the 2TH level CAGG don't affect others
DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL;
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:196: 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;
 bucket | temperature | device_id 
--------+-------------+-----------
      1 |          10 |         1
      2 |           2 |          
      2 |           5 |         2
      5 |          20 |         3
     10 |           2 |          

-- DROP the first CAGG should work
DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:203: NOTICE:  drop cascades to table _timescaledb_internal._hyper_6_14_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:206: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.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_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.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_functions.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, timescaledb.materialized_only=false) 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_functions.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_functions.cagg_watermark(11)::integer, '-2147483648'::integer)
  GROUP BY (time_bucket(2, conditions_summary_1.bucket));

\set ON_ERROR_STOP 1
\set VERBOSITY terse
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.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_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
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_TIME_DIMENSION
  SELECT table_name FROM create_hypertable('conditions', 'time');
psql:include/cagg_on_cagg_setup.sql:30: WARNING:  column type "timestamp without time zone" used for "time" does not follow best practices
 table_name 
------------
 conditions

\else
  SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10);
\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
  $$;
  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
ORDER BY 1, 2, 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
  , devices.device_id
  , devices.name
  FROM :CAGG_NAME_1ST_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id
  GROUP BY 1, 3, 4
  ORDER BY 1, 2, 3, 4
\else
  FROM :CAGG_NAME_1ST_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\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
  , :CAGG_NAME_2TH_LEVEL.name
  , devices.location
  FROM :CAGG_NAME_2TH_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id
  GROUP BY 1, 3, 4, 5
  ORDER BY 1, 2, 3, 4, 5
\else
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\endif
WITH NO DATA;
-- Check chunk_interval
\if :IS_TIME_DIMENSION
  SELECT h.table_name AS name, _timescaledb_functions.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_functions.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

\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;
 bucket | temperature | device_id 
--------+-------------+-----------

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
          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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
          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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

\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;
          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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
          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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
          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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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:172: 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:173: 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:174: 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:175: 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:179: NOTICE:  drop cascades to table _timescaledb_internal._hyper_16_18_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_3TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:182: 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;
          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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

-- DROP the 2TH level CAGG don't affect others
DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL;
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:196: 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;
          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 |          

-- DROP the first CAGG should work
DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:203: NOTICE:  drop cascades to table _timescaledb_internal._hyper_14_20_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:206: 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
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_TIME_DIMENSION
  SELECT table_name FROM create_hypertable('conditions', 'time');
psql:include/cagg_on_cagg_setup.sql:30: WARNING:  column type "timestamp without time zone" used for "time" does not follow best practices
 table_name 
------------
 conditions

\else
  SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10);
\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
  $$;
  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
ORDER BY 1, 2, 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
  , devices.device_id
  , devices.name
  FROM :CAGG_NAME_1ST_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id
  GROUP BY 1, 3, 4
  ORDER BY 1, 2, 3, 4
\else
  FROM :CAGG_NAME_1ST_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\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
  , :CAGG_NAME_2TH_LEVEL.name
  , devices.location
  FROM :CAGG_NAME_2TH_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id
  GROUP BY 1, 3, 4, 5
  ORDER BY 1, 2, 3, 4, 5
\else
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\endif
WITH NO DATA;
-- Check chunk_interval
\if :IS_TIME_DIMENSION
  SELECT h.table_name AS name, _timescaledb_functions.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_functions.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

\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;
 bucket | temperature | device_id 
--------+-------------+-----------

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
          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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
          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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

\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;
          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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
          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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
          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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
          bucket          | temperature | device_id |   name   
--------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
          bucket          | temperature | device_id |   name   | location 
--------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 |          20 |         3 | thermo_3 | London

-- 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:172: 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:173: 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:174: 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:175: 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:179: NOTICE:  drop cascades to table _timescaledb_internal._hyper_20_24_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_3TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:182: 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;
          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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

-- DROP the 2TH level CAGG don't affect others
DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL;
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:196: 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;
          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 |          

-- DROP the first CAGG should work
DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:203: NOTICE:  drop cascades to table _timescaledb_internal._hyper_18_26_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:206: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp_without_timezone(_timescaledb_functions.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_functions.to_timestamp_without_timezone(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp_without_timezone(_timescaledb_functions.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_functions.to_timestamp_without_timezone(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp_without_timezone(_timescaledb_functions.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_functions.to_timestamp_without_timezone(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp_without_timezone(_timescaledb_functions.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_functions.to_timestamp_without_timezone(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp_without_timezone(_timescaledb_functions.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_functions.to_timestamp_without_timezone(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
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_TIME_DIMENSION
  SELECT table_name FROM create_hypertable('conditions', 'time');
 table_name 
------------
 conditions

\else
  SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10);
\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
  $$;
  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
ORDER BY 1, 2, 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
  , devices.device_id
  , devices.name
  FROM :CAGG_NAME_1ST_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id
  GROUP BY 1, 3, 4
  ORDER BY 1, 2, 3, 4
\else
  FROM :CAGG_NAME_1ST_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\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
  , :CAGG_NAME_2TH_LEVEL.name
  , devices.location
  FROM :CAGG_NAME_2TH_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id
  GROUP BY 1, 3, 4, 5
  ORDER BY 1, 2, 3, 4, 5
\else
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\endif
WITH NO DATA;
-- Check chunk_interval
\if :IS_TIME_DIMENSION
  SELECT h.table_name AS name, _timescaledb_functions.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_functions.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

\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;
 bucket | temperature | device_id 
--------+-------------+-----------

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
            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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
            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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

\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;
            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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
            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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
            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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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:172: 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:173: 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:174: 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:175: 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:179: NOTICE:  drop cascades to table _timescaledb_internal._hyper_29_30_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_3TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:182: 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;
            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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

-- DROP the 2TH level CAGG don't affect others
DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL;
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:196: 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;
            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 |          

-- DROP the first CAGG should work
DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:203: NOTICE:  drop cascades to table _timescaledb_internal._hyper_27_32_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:206: 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
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_TIME_DIMENSION
  SELECT table_name FROM create_hypertable('conditions', 'time');
 table_name 
------------
 conditions

\else
  SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10);
\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
  $$;
  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
ORDER BY 1, 2, 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
  , devices.device_id
  , devices.name
  FROM :CAGG_NAME_1ST_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id
  GROUP BY 1, 3, 4
  ORDER BY 1, 2, 3, 4
\else
  FROM :CAGG_NAME_1ST_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\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
  , :CAGG_NAME_2TH_LEVEL.name
  , devices.location
  FROM :CAGG_NAME_2TH_LEVEL
  JOIN devices ON devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id
  GROUP BY 1, 3, 4, 5
  ORDER BY 1, 2, 3, 4, 5
\else
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  ORDER BY 1, 2
\endif
WITH NO DATA;
-- Check chunk_interval
\if :IS_TIME_DIMENSION
  SELECT h.table_name AS name, _timescaledb_functions.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_functions.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

\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;
 bucket | temperature | device_id 
--------+-------------+-----------

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
            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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
            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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

\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;
            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

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
            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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
            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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
 bucket | temperature | device_id | name | location 
--------+-------------+-----------+------+----------

-- 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;
            bucket            | temperature | device_id |   name   
------------------------------+-------------+-----------+----------
 Sat Jan 01 00:00:00 2022 UTC |           5 |         2 | thermo_2
 Sat Jan 01 00:00:00 2022 UTC |          10 |         1 | thermo_1
 Sun Jan 02 00:00:00 2022 UTC |          20 |         3 | thermo_3

SELECT * FROM :CAGG_NAME_3TH_LEVEL;
            bucket            | temperature | device_id |   name   | location 
------------------------------+-------------+-----------+----------+----------
 Mon Dec 27 00:00:00 2021 UTC |           5 |         2 | thermo_2 | Berlin
 Mon Dec 27 00:00:00 2021 UTC |          10 |         1 | thermo_1 | Moscow
 Mon Dec 27 00:00:00 2021 UTC |          20 |         3 | thermo_3 | London

-- 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:172: 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:173: 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:174: 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:175: 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:179: NOTICE:  drop cascades to table _timescaledb_internal._hyper_33_36_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_3TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:182: 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;
            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 |          

SELECT * FROM :CAGG_NAME_2TH_LEVEL;
 bucket | temperature | device_id | name 
--------+-------------+-----------+------

-- DROP the 2TH level CAGG don't affect others
DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL;
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_common.sql:196: 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;
            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 |          

-- DROP the first CAGG should work
DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:203: NOTICE:  drop cascades to table _timescaledb_internal._hyper_31_38_chunk
\set ON_ERROR_STOP 0
-- should error because it was dropped
SELECT * FROM :CAGG_NAME_1ST_LEVEL;
psql:include/cagg_on_cagg_common.sql:206: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: ERROR:  cannot create continuous aggregate with incompatible bucket width
DETAIL:  Time bucket width of "public.conditions_summary_2" [@ 1 year] 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: 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
\set CAGG_NAME_3TH_LEVEL conditions_summary_3
--
-- CAGG on hypertable (1st level)
--
CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL
WITH (timescaledb.continuous, timescaledb.materialized_only=false) 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_functions.to_timestamp(_timescaledb_functions.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_functions.to_timestamp(_timescaledb_functions.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, timescaledb.materialized_only=false) 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:44: ERROR:  cannot create continuous aggregate with incompatible bucket width
DETAIL:  Time bucket width of "public.conditions_summary_2" [@ 1 mon] 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
-- Check for incorrect CAGGs
\if :INTERVAL_TEST
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-15 01:00:00-00', 20, 4);
  INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-31 01:00:00-00', 30, 4);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL);
  CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL);
  CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL
  WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS
  SELECT
    \if :IS_TIME_DIMENSION_WITH_TIMEZONE_2TH
      time_bucket(:BUCKET_WIDTH_3TH, "bucket", :'BUCKET_TZNAME_2TH') AS bucket
    \else
      time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket
    \endif
  FROM :CAGG_NAME_2TH_LEVEL
  GROUP BY 1
  WITH DATA;
  \d+ :CAGG_NAME_3TH_LEVEL
  --There should never be dulpicates in the output of the following query
  SELECT * from :CAGG_NAME_3TH_LEVEL;
  DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL;
  DELETE FROM conditions WHERE device_id = 4;
\endif
--
-- Cleanup
--
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_2TH_LEVEL;
psql:include/cagg_on_cagg_validations.sql:86: NOTICE:  materialized view "conditions_summary_2" does not exist, skipping
DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL;
